The engineering team was using AI coding agents to build an automated trading platform. With a small team, the agents were doing most of the engineering work.
At the end of the week, the CTO opened AgentPM for a routine review of the previous week's agent activity. The goal was simple: understand what had changed and verify that everything looked as expected.
It didn't.
What started as a routine review quickly became a security investigation.
The platform had been built across Claude and Codex, working from different machines and committing directly to the repository. GitHub showed the final result, but not the conversations, decisions, or unfinished work that led there.
So instead of starting with the code, we started with the agent history.
This is that investigation, in the order it happened.
What have the agents actually been doing?
Not the commits — the activity. Which machines, which agents, how much work, at what cost. Before drilling into any one session we wanted the shape of the week. The org's home dashboard answers this without a query.

The dashboard tells us the fleet is real and busy, but not what it's pointed at. For that we drop to the CLI — the same read-only agentpm API the agents themselves use — and ask for the project rollup.
$ agentpm conv projects --org Meridian 40 projects · 1,391 conversations · 339,344 turns · 9.1B in / 23M out /home/dev/src/app-core claude 700 conv 96K turns 1.6B in /Users/dev/…/app-core codex 32 conv 34K turns 1.3B in /Users/dev/…/ops-dashboard claude+codex 42 conv 46K turns 2B in /Users/dev/…/agent-tools claude+codex 63 conv 42K turns 1.6B in … 36 more
The project rollup turns a week of scattered agent activity into a review map. It shows which directories were active, which agents worked there, how many conversations and turns accumulated, and where token volume clustered. Instead of guessing which chat history mattered, the CTO could narrow the review to the highest-signal projects first.
Did the agents touch anything risky?
On a trading system, "risky" has a specific meaning: credentials, live orders, auth. We didn't know which conversation to open, so we narrowed the search to the trading-platform project and asked AgentPM for conversations involving secrets, credentials, API keys, and related work.
$ agentpm conv search "secret credential api key" --cwd /home/will/src/Tradewind 4 conversation(s) for the project goc_5139acbc19e3f720956f8db1 Execution-issue report published after log review claude 512t goc_8f38b62e9d5a2dc83c1f980e Execution log triage and May 20 report publication claude 512t goc_43591a3b03a873404d5ab72d Investigate execution warnings and publish May 20 report claude 369t goc_48fe9d63abab27c950eca5df Norgate dump transfer, storage move, and backtest parity claude 15K t

The list gave the investigation a path. One thread was a long-running build session where credentials appeared in the open. The shorter report sessions showed the same project being reviewed later for execution issues and safety concerns. We opened the source conversation first, then used the shorter review threads to check what had been noticed afterward.
What happened?
We narrowed to the review conversation and asked it to surface just the danger. The find verb searches inside a single conversation and reports the turns where terms converge.
$ agentpm conv find goc_63101905ed70d0c1b4ccebb3 "dangerous flagged" strict turn hit → turn 68 (CLAUDE · concluded) 3 findings, each cited to a source conversation + turn range

The headline finding was blunt: a production admin token had been compiled into the front-end JavaScript bundle. We followed its citation straight to the source.
Why did it happen?
The citation pointed to conversation goc_71ec…, turns 646–689. We jumped directly to the turn — no scrolling through seven thousand.
$ agentpm conv show --turn 655 goc_71ec51d033ff81398744ae6a [655] assistant "the compiled JS literally contains the god token … a leaked public env token in the browser bundle." $ agentpm conv show --turn 646 goc_71ec51d033ff81398744ae6a [646] assistant "If the client bundle includes NEXT_PUBLIC_AUTH_TOKEN, every browser effectively carries the god API key."
NEXT_PUBLIC_AUTH_TOKEN in the compiled bundle — plus the conversation header showing its size ($233, 7,212 turns) to convey the haystack this needle sat in.

NEXT_PUBLIC_ prefix inlines a value into the browser bundle. So a single environment variable turned an admin key into public knowledge. This is the reasoning GitHub never captured — and it's sitting at turn 646 of a session no human would ever have scrolled to by hand."If the client bundle includes NEXT_PUBLIC_AUTH_TOKEN, every browser effectively carries the god API key."
goc_71ec51d033ff81398744ae6a · turn 646 — verbatim
We had the what and the why. But an agent claiming it fixed something is not the same as it being fixed. The next question was the one an auditor actually cares about.
What changed — and did it stick?
The remediation happened in a separate session, goc_b6109… — "Broker-secret encryption implemented and deployed." We asked for its mutating git operations only, to skip the narration and see the actions.
$ agentpm conv git goc_b6109e169415797ffdf3fe3d --mutating-only # the agent had run, live, on the production host: dev@tradewind$ ssh dev@host-b 'cd ~/src/Tradewind \ && git rev-parse --short HEAD && git rev-parse --short origin/main \ && git status --short -- apps/api-v2/app/auth.py apps/api-v2/app/security' head=ba9a213 origin_main=ba9a213 M apps/api-v2/app/auth.py M apps/api-v2/tests/test_broker_secret_storage.py
Read quickly, head == origin_main looks reassuring — in sync. But the security files were modified and uncommitted. The fix was running on the server and existed nowhere in the repository. A live behavior probe confirmed the protection was actually up:
dev@tradewind$ ssh dev@host-b 'curl -s -o /dev/null -w "%{http_code}" :8001/ ; …' api_root=200 admin_chat_unauth=401 expired_session_rejected=True forged_clerk_rejected=True
head=ba9a213 / origin_main=ba9a213 with the M uncommitted auth files) and the four-word conclusion at turn 750.

"Deployed: yes. In main: no."
goc_b6109e169415797ffdf3fe3d · turn 750 — verbatim
One git checkout . or a fresh clone would have silently reverted the entire security hardening. It was caught, and a few turns later — after the human said "lets commit" — resolved: "Done. It's now deployed and in main." Which raised the question of who was making these calls, and why the design looked the way it did.
Who decided this?
The hardening didn't start with code. It started with a question from the human operator, preserved at turn 2 of the encryption session — typos and all, which is part of why it reads as real:
"if we are toring tokens to auth brokerage accounts how to we majke sure to ahve the upmost security"
goc_b6109e169415797ffdf3fe3d · turn 2 — the human, verbatimThe agent's answer is where the decision was actually made. It compared the stated posture to the real storage and found the gap:
trade_accounts.py:35 (secret stripped from browser responses) versus daily_db.py:127 (a plain TEXT column) — with the line "That is not 'utmost security' yet."

So the chain was human intent → agent audit → a concrete standard → implementation → deployment → the commit-drift catch. Every link visible, every link cited. Which left the question every handoff eventually hits.
Was anything left unfinished?
We asked AgentPM for the recent work on the trading checkout, across every agent, and looked for threads that ended parked rather than done.
$ agentpm conv work --cwd ~/src/Tradewind goc_898a03759d668de5176fbaca codex Live trade health check & broker-truth reconciliation goc_188a315c49bfb3fc6b0d67fd codex the brokerage / Schwab integration — parked, not broken $ agentpm conv show --turn 1 --json goc_188a315c49bfb3fc6b0d67fd { "ok": true, "agent_id": "agt_f3cbac5443b9944c1d23861e", "org": "Meridian", "conversation": { "id": "goc_188a315c49bfb3fc6b0d67fd", "title": "…look into plugging in the brokerage and Schwab accounts…" } }
There it was: the brokerage integration, parked. Not broken — the thread simply ended mid-effort, the paper account left needing a reset. In a normal workflow that context dies with the session. The obvious next move was to test whether it actually had to.
Unfinished work isn't rare — it's the default. Agents stop when context runs out, when a human steps away, when a task turns out bigger than a session. The question isn't whether work gets parked. It's whether the next agent can find it.
Can another agent continue the work?
We didn't have to hypothesize; it had already happened. On July 7, an engineer asked a fresh Claude agent to pick up work a Codex session had been driving the day before — the integration with the trading platform's brokerage:
you ▸ lets continue work on the Tradewind trading platform, lets check agentpm to see where we left off on the brokerage integration from yesterday on codex agent ▸ loading skill: agentpm-conversations … $ agentpm conv work --cwd ~/src/Tradewind $ agentpm conv find goc_898a03759d668de5176fbaca "the brokerage remaining next" agent ▸ Here's where things stand with the brokerage integration on Tradewind: • Prior work was Codex, yesterday — reconciliation shipped • Open: live-order gating still behind automation_enabled • Parked: the brokerage paper account (goc_188a…) needs a reset • Resuming there — not from scratch.

"lets check agentpm to see where we left off on the brokerage integration from yesterday on codex."
goc_6c5d7affd44aa0ba1f06d043 · turn 0 — verbatim
The new agent didn't reconstruct that state from memory or from GitHub; it read the prior Codex session out of the shared record and resumed from the known point. One more question remained.
What patterns do we see across the organization?
Individual conversations tell you what happened once. To see how the org works, AgentPM reads across all of them. The dashboard's coaching band is the aggregate of 1,400 analyzed sessions.
exec_command alone ran 41K times for 1.6B tokens.

CLAUDE.md. None of this is visible in any single conversation — only in the aggregate.The coaching view named the class of problem the earlier questions had been circling one instance at a time. The god token, the commit drift, and the parked brokerage work share a signature: long, unsegmented sessions doing high-stakes work at speed. The evidence supports that reading; on its own it does not establish cause.
We started asking what the agents did last week. Nine questions later we understood an entire engineering effort: a credential leak and its root cause, a security fix that nearly reverted itself, the human intent behind the design, the work left parked, the agent that resumed it, and the organizational habit underneath all of it.
Not one of those answers came from GitHub. Every one came from the conversations.
So what does the org do Monday?
An investigation that only explains the past is a parlor trick. This one came with a to-do list — because the same coaching pass that counted the anti-patterns also named the fixes, and it read across 1,400 sessions instead of one. The fixes are unglamorous, which is usually how you can tell they're the real ones.
138 — significant work started with no plan on record. Put a planning step before the first edit.
85 — sessions long enough to lose the thread. Segment and checkpoint instead of running one unbroken marathon.
30 — corrections repeated often enough to belong in CLAUDE.md. Write each one down once so nobody re-types it.
That's the quiet case for keeping a record over coding agents at all. They make the team faster and make the story of why the software is the way it is more fragile — because the author is a process that forgets. The record has to live somewhere that doesn't. The trading platform was fine in the end: the token rotated, the fix committed, the parked work resumed. What would not have been fine was learning any of it by accident, weeks later, from a stranger's browser holding an admin key. That difference wasn't a smarter agent — it was a record you could ask questions of.
You don't need to know where something happened. You ask AgentPM, and follow the answer to the next question.