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.
You need a few things in place before observability for AI coding agents is worth the effort.
Prerequisites
main protectedMental model
Observability for coding agents needs three layers:
We’ll wire logs and IDs through all three so you can answer:
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:
session_id: stable per agent sessionagent_name: e.g. claude-code, cursor-agentorchestrator_id: the orchestrator session the work belongs toconversation_id: maps to chat history, if your tool exposes onerepo: e.g. org/service-apibranch: feature/agent-123-add-metricscommit_range: from base_sha to last agent commit SHAgoal: one-line brief from the orchestrator (e.g. "add latency histogram to /users")scope: paths or modules the agent is allowed to touchconstraints: e.g. "no DB schema changes", "no infra files"tools_used: test runners, linters, code generators, etc.commands_run: shell commands the agent asked to executefiles_touched: list of filestests_run and tests_statusmodel_name: e.g. gpt-4.1, claude-3.5-sonnetinput_tokens, output_tokensduration_mstool_latency_ms for slow toolsstatus: working, idle, waiting_on_user, blocked, done, dead, not_heard_frompossibly_stalled: bool overlay when nothing has been heard from the session in a whileresult: draft, ready_for_review, abortedThis 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.
Maxxwell’s job is to be the agent session monitoring dashboard for your local fleet, without hiding your terminals.
From your repo root:
cd ~/src/service-api
maxxwell
Maxxwell will:
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.
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:
working, waiting_on_you, needs_sign_in, etc.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.
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:
orchestrator_id → feature branchworker_session_id → subset of commits on that branchBefore 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.
Once the branch exists, record the mapping so your logs stay consistent.
You can do this two ways:
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]"
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.
You don’t need a SaaS observability product to get useful logs. Plain text plus a consistent schema goes a long way.
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"
}
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.
Logging locally is only useful if reviewers can see it. Treat session logs as audit artifacts.
In GitHub:
main:GitHub’s docs are explicit: branch protections and status checks are the boundary where agent-produced changes either land or not.
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.
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?".
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.
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.
If you already run an observability stack, you can push a subset of the GenAI semantic conventions.
OpenTelemetry’s GenAI guidance suggests attributes like:
gen_ai.agent.idgen_ai.conversation.idgen_ai.input_tokensgen_ai.output_tokensA 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.
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:
working, waiting_on_you, blocked, not_heard_from.possibly_stalled overlay when it hasn’t seen activity.You use this to decide where your attention goes.
With Maxxwell’s session dashboard open:
waiting_on_you and blocked.possibly_stalled plus high context pressure, decide whether to: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.
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.
To make this concrete, here’s an end-to-end path you can adopt:
.agent-logs/<session_id>.jsonl.agent: and goal: markers.You now have traceability from agent session to commit to deploy, with minimal extra machinery.
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.
Log at least:
session_id, agent_name, orchestrator_id)ready_for_review, aborted, etc.)This is enough to debug behavior and audit changes.
Use shared IDs:
[agent:<session_id>] in commit messages.session_id in .agent-logs/<session_id>.jsonl.goal_id as well.Reviewers can then jump from commit → session log → goal.
Maxxwell:
It does not auto-correct drift or recycle sessions; it keeps you in the loop.
Yes. You can:
.agent-logs/*.jsonl.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.