AI coding agents are drowning in context: how to cut tool-output noise by 98% without losing session memory
I’m Denis Shokhirev, an Agentic AI Systems Architect based in Freiburg im Breisgau, Germany, and at DennisCraft AI Studio I ship production AI systems for DACH B2B teams on Claude, Supabase, n8n, Doppler, and self-hosted Postgres. The most expensive failure mode I see in coding agents is not model quality. It is context collapse: after a few tool calls, the agent is carrying pages of stdout, test logs, and file dumps, but it can no longer explain why it touched the code in the first place. This
I’m Denis Shokhirev, an Agentic AI Systems Architect based in Freiburg im Breisgau, Germany, and at DennisCraft AI Studio I ship production AI systems for DACH B2B teams on Claude, Supabase, n8n, Doppler, and self-hosted Postgres. The most expensive failure mode I see in coding agents is not model quality. It is context collapse: after a few tool calls, the agent is carrying pages of stdout, test logs, and file dumps, but it can no longer explain why it touched the code in the first place.
This gets worse in regulated environments. Once the agent burns its window on raw tool output, you lose not only tokens but decision traceability. The next session restarts from fragments, repeats file reads, and often produces inconsistent edits. If you are trying to run an autonomous coding loop instead of a demo, that is where your costs and defects pile up.
The actual problem is not tools. It is unfiltered return traffic.
Most teams focus on what tools the agent can call: grep, semgrep, bandit, gitleaks, tests, diffs, database introspection. That is the easy part. The hard part is deciding what comes back into the model context after each call.
| Pattern | What the agent gets back | Typical result |
|---|---|---|
| Raw passthrough | Full stdout/stderr and file chunks | Context fills with logs |
| Naive truncation | First N lines only | Critical findings are often missed |
| Structured summarization | Status, findings, touched files, next action | Low token use and stable recall |
Anthropic’s documentation on tool use and prompt design consistently pushes toward structured, bounded context rather than uncontrolled transcript replay. OpenAI’s Cookbook makes a similar point for long-context and retrieval workflows: keep relevant state compact and fetch detail only when needed. See Anthropic Docs, 2024–2025, https://docs.anthropic.com/ and OpenAI Cookbook, 2024, https://cookbook.openai.com/.
On recent client systems, I have reduced tool-output content reintroduced into the model by about 98%. That did not require fewer tools. It required better serialization of tool results.
What should stay in the prompt, and what should not
Keep decision state, not operational exhaust
The model does not need a full bandit report or a 400-line test run in every turn. It needs a compact state object: what goal it is pursuing, what files changed, what issues were found, what has already been fixed, and what the next action should be.
Persist raw artifacts outside the model
Store complete outputs in Postgres or Supabase with run identifiers and metadata. Put only normalized summaries in the prompt. If the model needs detail, let it explicitly ask for one artifact or one file section.
Session memory is not chat history
This is where many agent implementations go wrong. Replaying the whole conversation is usually a weak substitute for a compact task state. Session memory should be explicit: goal, constraints, architectural decisions, touched files, open risks, and next step.
from dataclasses import dataclass, asdict
import json
@dataclass
class SessionMemory:
goal: str
constraints: list[str]
decisions: list[str]
touched_files: list[str]
open_risks: list[str]
next_action: str
def serialize_memory(memory: SessionMemory) -> str:
return json.dumps(asdict(memory), separators=(",", ":"))
memory = SessionMemory(
goal="Replace SQL string interpolation with parameters",
constraints=["Keep public repository API unchanged"],
decisions=["Use parameterized queries", "Patch tests before refactor"],
touched_files=["app/repo.py", "tests/test_repo.py"],
open_risks=["Legacy helper still builds raw SQL"],
next_action="Inspect helper and patch failing tests"
)A production pattern that stays stable across sessions
The pattern I use is simple: execute, normalize, persist, recall.
Execute
Run the tool exactly as needed. semgrep, bandit, gitleaks, unit tests, git diff, whatever your loop requires.
Normalize
Convert raw output into a fixed schema. For example: tool name, status, finding count, affected files, top issue, suggested next action. Fixed schemas matter because they keep the return channel predictable for the model.
Persist
Write both the raw artifact and the normalized summary to Postgres. For regulated work, this also improves auditability because you can show what the agent saw and how the orchestration layer compressed it.
Recall
Start a later session from compact memory, not from transcript replay. Pull a raw artifact only if the current step requires it.
type ToolSummary = {
tool: string
status: "ok" | "fail"
findings: number
files: string[]
nextAction: string
}
function summarizeSemgrep(json: any): ToolSummary {
const results = json.results ?? []
const files = [...new Set(results.map((r: any) => r.path))]
return {
tool: "semgrep",
status: results.length ? "fail" : "ok",
findings: results.length,
files: files.slice(0, 10),
nextAction: results.length ? "patch flagged paths" : "continue"
}
}Why this matters for security reviews
When agents are overloaded with logs, they miss the signal that matters. In code generation and repair loops, that often means security defects survive because the model is busy carrying incidental output. OWASP’s Top 10 remains a useful anchor here because the classes of application risk have not changed just because code is now machine-authored. Injection, broken access control, and secrets exposure still show up in AI-assisted code if your outer loop does not catch them. Source: OWASP Top 10, 2021, https://owasp.org/www-project-top-ten/.
That is why I treat external checks as mandatory gates in autonomous coding workflows: semgrep for pattern scanning, bandit for Python, gitleaks for secret detection, plus tests. The key detail is that the model sees only a normalized result unless it requests a specific raw artifact.
#!/usr/bin/env bash
set -euo pipefail
semgrep --config auto --json > /tmp/semgrep.json || true
bandit -r . -f json -o /tmp/bandit.json || true
gitleaks detect --report-format json --report-path /tmp/gitleaks.json || true
python scripts/store_results.py \
--run-id "$RUN_ID" \
--semgrep /tmp/semgrep.json \
--bandit /tmp/bandit.json \
--gitleaks /tmp/gitleaks.jsonThe minimum implementation
You do not need a new platform for this. If you already have Claude Code, the Anthropic SDK, n8n, or your own orchestrator, add 3 things:
| Object | Store | Purpose |
|---|---|---|
| tool_runs | Postgres / Supabase | Raw outputs and metadata |
| session_memory | Postgres / Supabase | Compact task state |
| recall_policy | Orchestrator code | Rules for what can re-enter the prompt |
In n8n, this is usually one node to run checks, one node to normalize JSON, one node to write to storage, and one node to assemble the next prompt from memory plus the smallest necessary evidence. Tool output is a log stream. It should not become your working memory.
FAQ
Should I store full chat transcripts?
Usually no. For coding agents, full transcripts are expensive and often low-value. Store decisions, constraints, artifacts, and references to raw logs instead.
Is this just RAG?
Not exactly. RAG is useful for searching code, docs, or past runs. Session memory is a separate structured state object that represents the current task and its decisions.
Can I do this without Supabase?
Yes. Plain Postgres is enough. Supabase is convenient if you already use it for API access and auth.
Why not just buy more context?
Because the issue is not only context size. It is context quality. A larger window still fails if the signal is buried under operational exhaust.
How do I measure whether this worked?
Track tokens per successful task, repeated file reads per run, restart success rate across sessions, and time-to-fix after an interrupted run. Those metrics show whether memory is actually carrying useful state.
If you already run coding agents in production, where does quality degrade first in your loop: raw tool output, repeated file reads, or weak session memory across restarts? I would genuinely like to compare that with what I am seeing in current client systems.
I run a free 30-min stack audit for DACH founders building AI in regulated markets. DM me on LinkedIn or write to @ger_dennis_ai.
Turn your process into an AI system
Production quality. DACH B2B focus.