Maxxwell by Rindler
Writing

Logging AI coding agents into Git and CI

2026-09-24

You can run eight agent sessions just fine. You become the bottleneck when you can’t see which one is doing what, which commit came from which session, or why.


You can run eight agent sessions just fine. You become the bottleneck when you can’t see which one is doing what, which commit came from which session, or why CI just burned $50 of tokens.

This tutorial walks through a concrete setup: what to log for coding agents, and how to wire those logs into a Git-based workflow with reviews, checks, and deployments. The examples assume Maxxwell as the agent orchestrator, but the Git and CI pieces are generic.

We treat this as an "agent-native" workflow. If you want the bigger-picture definition of agent-native development, see the related guide: Agent-native development: a working definition.


1. Prerequisites and mental model

You need a few things in place before observability for AI coding agents is worth the effort.

Prerequisites

  1. A Git repo with CI:
    • GitHub repo
    • Existing CI (GitHub Actions, CircleCI, etc.)
  2. One or more coding agents you already use:
    • Claude Code, Codex, Cursor agent, etc.
  3. Maxxwell installed locally:
    • Desktop or CLI
    • Configured with your own API key(s)
  4. A basic branch strategy:
    • main protected
    • feature branches via PR

Mental model

Observability for coding agents needs three layers:

  1. Session layer - what each agent is doing, with identity and context.
  2. Git layer - how session output maps to branches, commits, and PRs.
  3. CI/CD layer - how those commits trigger checks and deployments.

We’ll wire logs and IDs through all three so you can answer:


2. What to log for coding agents (minimum viable schema)

OpenTelemetry’s GenAI conventions and GitHub’s Copilot session logs are converging on the same shape. You don’t have to adopt OTLP to copy the structure.

For coding agents, log at least these fields per session:

  1. Identity and context
    • session_id: stable per agent session
    • agent_name: e.g. claude-code, cursor-agent
    • orchestrator_id: the orchestrator session the work belongs to
    • conversation_id: maps to chat history, if your tool exposes one
  1. Repo and branch
    • repo: e.g. org/service-api
    • branch: feature/agent-123-add-metrics
    • commit_range: from base_sha to last agent commit SHA
  1. Work intent
    • goal: one-line brief from the orchestrator (e.g. "add latency histogram to /users")
    • scope: paths or modules the agent is allowed to touch
    • constraints: e.g. "no DB schema changes", "no infra files"
  1. Decisions and actions
    • tools_used: test runners, linters, code generators, etc.
    • commands_run: shell commands the agent asked to execute
    • files_touched: list of files
    • tests_run and tests_status
  1. Telemetry and cost
    • model_name: e.g. gpt-4.1, claude-3.5-sonnet
    • input_tokens, output_tokens
    • duration_ms
    • tool_latency_ms for slow tools
  1. Outcome and status
    • status: working, idle, waiting_on_user, blocked, done, dead, not_heard_from
    • possibly_stalled: bool overlay when nothing has been heard from the session in a while
    • result: draft, ready_for_review, aborted

This is enough to answer the OpenTelemetry-style question: "was it the model, a slow tool, or a retry loop?" and to give reviewers an audit trail.

You can expand into full OTLP later. The core is: every agent action should be traceable to a session, a branch, and a goal.


3. Configure Maxxwell to track sessions and Git state

Maxxwell’s job is to be the agent session monitoring dashboard for your local fleet, without hiding your terminals.

Step 3.1: Start Maxxwell in a repo

From your repo root:

cd ~/src/service-api
maxxwell

Maxxwell will:

Step 3.2: Write a brief that encodes the goal and constraints

In the orchestrator, write a brief that becomes the goal and scope for downstream logs:

Goal: Add request latency histograms to the /users API.
Scope: backend/service-api repo only. Touch only handlers and metrics wiring.
Constraints: No DB schema changes. Tests must pass locally.
Definition of done: histogram visible in metrics endpoint with basic test coverage.

Maxxwell keeps this brief attached to the orchestrator session, so the goal stays visible while the workers run.

Step 3.3: Create worker sessions per concern

From the orchestrator, ask it to spin up workers:

Start one worker to update the handlers and metrics wiring.
Start another worker to adjust tests and snapshot any new metrics endpoints.

Maxxwell will:

At this point, observability exists in Maxxwell’s UI: you see each session’s state and live context pressure (tokens vs context limit), with warnings when you’re close to the edge.


4. Map agent sessions to Git branches

Git is the governance boundary: branch protections and merge queues are where agent work either stops or ships.

You want one branch per goal, with a stable mapping:

Step 4.1: Create a feature branch per orchestrator

Before letting agents write code, have Maxxwell draft the branch setup.

From the orchestrator, ask:

Plan the Git steps to implement this goal safely:
- Create a feature branch from main with a clear name.
- Ensure no commits land on main directly.
- Stage and commit files in small, reviewable chunks.
Do NOT run these commands; draft them for me to inspect.

Maxxwell’s fleet control is "drafts rather than acts". It will write a command sequence into its composer, but won’t run it until you hit enter.

You’ll see something like:

git fetch origin
git checkout -b feature/latency-histograms origin/main

Inspect, then run the commands yourself.

Step 4.2: Record branch metadata in session logs

Once the branch exists, record the mapping so your logs stay consistent.

You can do this two ways:

  1. Convention in commit messages

Have agents include a session marker, which GitHub can later link back to logs:

   git commit -m "Add /users latency histogram [agent:worker-7a3c] [goal:latency-hists]"
  1. Environment variables for tools

When launching workers under Maxxwell, set environment vars:

   export AGENT_SESSION_ID="worker-7a3c"
   export AGENT_GOAL_ID="latency-hists"
   export AGENT_ORCHESTRATOR_ID="orch-002"

Your scripts can then emit logs with these fields.

Either way, the important piece is that each commit and each session log shares a common session_id and goal_id.


5. Log agent decisions and actions locally

You don’t need a SaaS observability product to get useful logs. Plain text plus a consistent schema goes a long way.

Step 5.1: Create a local agent log file

In your repo, add a simple log directory:

mkdir -p .agent-logs

Each session can append to a file like .agent-logs/<session_id>.jsonl.

Example entry:

{
  "timestamp": "2026-09-04T16:12:03Z",
  "session_id": "worker-7a3c",
  "orchestrator_id": "orch-002",
  "goal": "add request latency histograms to /users API",
  "repo": "org/service-api",
  "branch": "feature/latency-histograms",
  "files_touched": [
    "handlers/users.go",
    "metrics/latency.go"
  ],
  "commands_run": [
    "go test ./...",
    "make metrics-check"
  ],
  "tests_status": "pass",
  "model_name": "claude-3.5-sonnet",
  "input_tokens": 2489,
  "output_tokens": 1563,
  "duration_ms": 87234,
  "status": "ready_for_review"
}

Step 5.2: Wire simple logging into your agent wrapper

If you start agents via a script, add logging there.

# scripts/run_agent_session.sh
SESSION_ID="$1"
GOAL_ID="$2"
LOG_FILE=".agent-logs/${SESSION_ID}.jsonl"

# ... start your agent process ...

log_event() {
  jq -nc \
    --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
    --arg session "$SESSION_ID" \
    --arg goal "$GOAL_ID" \
    --arg status "$1" \
    '{timestamp:$ts, session_id:$session, goal_id:$goal, status:$status}' \
    >> "$LOG_FILE"
}

log_event "started"
# later: log_event "ready_for_review"

This is crude but effective. You now have a searchable audit trail per session without leaving your repo.


6. Connect agent logs to GitHub PRs

Logging locally is only useful if reviewers can see it. Treat session logs as audit artifacts.

Step 6.1: Enforce branch protections

In GitHub:

  1. Go to Settings → Branches.
  2. Add a protection rule for main:
    • Require PRs
    • Require status checks to pass
    • Require at least one review

GitHub’s docs are explicit: branch protections and status checks are the boundary where agent-produced changes either land or not.

Step 6.2: Create a lightweight PR template for agent work

Add .github/pull_request_template.md:

### Agent session

- Orchestrator: `{{ orch-id }}`
- Worker sessions:
  - `worker-7a3c` - handlers + metrics
  - `worker-8b1d` - tests and fixtures

Logs: `.agent-logs/` contains JSONL per session.

### Summary

- Goal: {short goal}
- Scope: {paths touched}

### Validation

- [ ] Unit tests
- [ ] Integration tests (if any)
- [ ] Manual check of metrics endpoint

Encourage agents to populate the summary (via Maxxwell’s orchestrator) but keep the validation checklist for humans.

Step 6.3: Attach session IDs in PR descriptions

From Maxxwell’s orchestrator, ask for a PR description draft:

Draft a PR description:
- Include orchestrator and worker IDs.
- Summarize goal and constraints.
- Link to .agent-logs files by path.
Do not open the PR; just draft the body.

Again, Maxxwell drafts rather than acts. You paste into GitHub manually.

Now every PR answers: "which agent did this, under what goal, with which logs?".


7. Trigger CI and deployments safely from agent-generated branches

Once agent work is on a branch, CI should behave the same as human work. The difference is that you care more about observability: token usage, time per run, tool failures.

Step 7.1: Standard CI on every push

A minimal GitHub Actions workflow:

# .github/workflows/ci.yml
name: CI

on:
  push:
    branches:
      - main
      - feature/**
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version: '1.22'
      - name: Run tests
        run: |
          go test ./... -json > test-report.json

      - name: Attach agent metadata
        if: always()
        run: |
          if [ -d .agent-logs ]; then
            echo "Agent logs present:";
            ls .agent-logs;
          fi

This doesn’t parse logs yet, but it ensures those files are part of the CI context.

Step 7.2: Optional - Export minimal OTLP-style metrics

If you already run an observability stack, you can push a subset of the GenAI semantic conventions.

OpenTelemetry’s GenAI guidance suggests attributes like:

A simple approach is to have a job that parses .agent-logs/*.jsonl and emits a small OTLP batch.

You do not have to go full OTLP to benefit. Even a CSV artifact with session_id, tokens, duration_ms lets you spot the run that spent 20x more than expected.


8. Use Maxxwell to detect stalled or drifting sessions

Stack Overflow’s 2025 survey says 51% of professional developers are using AI tools daily, but trust has dropped to about 60%. A big reason is sessions that stall or drift silently.

Maxxwell does not auto-correct drift or restart work. Instead, it surfaces:

You use this to decide where your attention goes.

Step 8.1: Triage via Maxxwell instead of twelve terminals

With Maxxwell’s session dashboard open:

This is the "observability instead of blind trust" layer. You see which sessions are progressing, which are idle, and which are quietly building the wrong thing.

Step 8.2: Use the return report to separate "landed" from "pending" work

When a goal wraps up, ask the orchestrator:

Summarize this goal:
- Which changes have landed on the feature branch (list commits)?
- Which work is still pending or blocked?
- What decisions did you make without asking me?
Draft a short return report I can paste into the PR.

Because the orchestrator is itself a coding-agent session in your repo, it can read the logs and Git state and draft a report that separates:

This is your review companion: you know exactly what you’re approving.


9. Example: End-to-end flow for an agent-driven change

To make this concrete, here’s an end-to-end path you can adopt:

  1. Brief a goal in Maxxwell’s orchestrator.
  2. Create a feature branch drafted by Maxxwell, run by you.
  3. Spawn workers for code, tests, docs.
  4. Log every session to .agent-logs/<session_id>.jsonl.
  5. Commit with agent: and goal: markers.
  6. Push the branch and open a PR using the template.
  7. Run CI on push; examine tests and logs.
  8. Review using Maxxwell’s return report + PR diff.
  9. Merge once protections and reviews pass.
  10. Deploy via your existing pipelines.

You now have traceability from agent session to commit to deploy, with minimal extra machinery.


FAQ: Observability for coding agents

What is observability for AI coding agents?

Observability for AI coding agents is the practice of logging and tracing how agents behave: which sessions ran, what they changed, which tools they used, how many tokens they consumed, and how that work flowed into Git, CI, and deployments.

It borrows from OpenTelemetry’s GenAI semantic conventions and adds Git-specific context like branches, commits, and PRs.

What should I log for coding agents by default?

Log at least:

This is enough to debug behavior and audit changes.

How do I trace from an agent session to a commit?

Use shared IDs:

Reviewers can then jump from commit → session log → goal.

How does Maxxwell help with observability?

Maxxwell:

It does not auto-correct drift or recycle sessions; it keeps you in the loop.

Can I use this setup without Maxxwell?

Yes. You can:

Maxxwell makes the orchestration and visibility easier, especially once you cross three or four parallel sessions, but the Git and CI wiring works either way.