AI coding

A Task Log for Agent Work: What Was Asked and What Shipped

Antonio Evans8 min read

A split view: on the left, a developer's screen shows a chat prompt and a code diff; on the right, a structured table with columns for task ID, prompt, diff link, and review status.
Key points

Key points

  1. 1Keep one log entry per agent task with the task ID, the exact prompt, the diff or output returned, and the review outcome.
  2. 2Store the log where both people and agents can read it, ideally version-controlled Markdown next to the code it describes.
  3. 3Load the last few entries at the start of every session and handoff so the agent works from recorded evidence rather than a summary from memory.
  4. 4Log rejected and abandoned tasks too, because the reasons a diff failed are what stop the next slice from repeating the same mistake.

Why a log beats memory when work spans sessions

An agent session ends, and everything the agent learned goes with it. The next session starts cold: the model sees whatever you paste in, and nothing else. Sebastian Raschka's breakdown of coding agents makes the point that the harness, meaning tool use, context management and memory, plays as large a role as the model itself in how capable a coding agent feels in practice. A task log is the cheapest form of that memory you can own outright, because it is just text you control.

The problem the log solves is concrete. Long-horizon agent work degrades as context accumulates: research on context management for long tasks describes how accumulated context causes long-context degradation and reasoning failures, and shows that pruning stale content while preserving task constraints and progress improves outcomes across agents. A log is the manual version of that idea. Instead of carrying every tool call forward, you carry a short, structured record of what was asked and what shipped.

There is a second, subtler failure. Work presented to an agent as a long pre-filled trajectory from a weaker run can cause goal drift, even in strong models according to a survey of long-horizon planning. Pasting a raw transcript as "here is what we did" is exactly that pattern. A distilled log entry, with the prompt and outcome but not the 40 tool calls in between, avoids it.

The decision rule: if the next task depends on facts the current session discovered (file paths, constraints, the reason a test fails), those facts go in the log. If they are noise from an exploratory detour, they do not.

The fields that earn their place

Most teams that try a task log over-collect on day one and stop writing entries by day three. Keep the schema small enough that writing an entry takes under a minute, and detailed enough that a stranger (or an agent) can reconstruct the decision.

FieldWhat it holdsWhy it matters
task_idStable identifier, e.g. AUTH-142Lets a later entry or a review comment point back to the exact task
requestedOne or two sentences of the human ask, in the requester's wordsKeeps the original intent separate from your restatement of it
promptThe exact prompt text sent to the agent, verbatimWithout it you cannot tell whether a bad diff was a reasoning failure or a prompt failure
spec_refLink to the spec or plan file the prompt was built fromSpecs, not prompts, are the durable source of truth in spec-driven work according to Microsoft's SDD guidance
artifactThe diff, commit SHA, or output file pathReviewers read the artifact, not a description of it
reviewaccepted, accepted-with-edits, rejected or abandoned, plus one line of reasoningThe reasoning is the reusable part
evidenceTest command and result, or a link to the CI runTurns "looks fine" into something checkable
nextThe concrete next sliceRemoves the "where were we?" conversation at handoff

Two fields are easy to omit and expensive to omit. The first is the verbatim prompt: the difference between a prompt that produced an accepted diff and one that produced a rejected diff is often a single missing constraint, and you can only see that if both are recorded. The second is the review reasoning. A bare rejected tag tells the next session nothing; rejected: retried on 429 but not on 500, spec says retry all 5xx tells it everything.

Treat the prompt as a versioned artifact rather than a throwaway. Prompt and agent-description quality is a known source of routing and behavior errors, and precise descriptions of what a tool or agent does, with inputs and outputs spelled out, reduce them per Oracle's agent prompt guidance. Your log is where that precision accumulates.

Where to store the log

The storage decision mostly answers one question: can both the human and the agent read and write it with the tools they already have? Agents can read files, run shell commands and call HTTP endpoints. People read rendered Markdown and diffs. Choose the overlap.

Version-controlled Markdown in the repo. One file per task under something like docs/tasks/, with the prompt in a fenced block and the diff referenced by commit SHA. Agents can read it with a file tool, humans get it in the PR, and it is reviewable. This is the best default for code work.

An append-only JSONL file. One JSON object per line, one line per task. Good when you want to script over the log: compute acceptance rate per prompt template, or select the last five entries automatically. Agents parse it trivially.

A database or issue tracker. Best when multiple people and multiple agents share the log across machines. The cost is that agents need a tool to query it, so you must give them one.

The chat transcript. Worst option. Transcripts are long, unstructured, and invite the goal-drift pattern described earlier. Keep transcripts as raw material; never use them as the handoff artifact.

A workable hybrid: a small index file at a fixed path that agents always read first, plus per-task entries. The index carries the last few tasks and a pointer to the full history.

{"task_id":"AUTH-142","requested":"Reject expired reset tokens","spec_ref":"docs/specs/auth-reset.md","prompt":"See docs/tasks/AUTH-142-prompt.md","artifact":"commit 3f9a2c1","review":"accepted-with-edits","evidence":"pytest tests/auth -q: 41 passed","next":"Add rate limit on reset endpoint"}
{"task_id":"AUTH-143","requested":"Rate limit reset endpoint","spec_ref":"docs/specs/auth-reset.md","prompt":"See docs/tasks/AUTH-143-prompt.md","artifact":"commit 8b1d4e0","review":"rejected","evidence":"pytest tests/auth -q: 3 failed (token bucket off-by-one)","next":"Fix bucket refill math, re-run"}

One practical note on prompts: store them in files and reference them from the log line. Fenced blocks inside JSON are painful to diff and review. The JSONL entry stays small, and the prompt file is what you actually edit and compare across tasks.

Writing an entry as part of the task, not after it

A log written from memory at the end of the day drifts toward success stories. The reliable pattern is to create the entry before the agent runs, then fill in the outcome.

  1. Create the task ID and write requested, spec_ref, and the prompt file before you send anything.
  2. Send the prompt exactly as written. If you improvise extra instructions in the chat box, update the prompt file and note the edit, otherwise the log lies about what the agent saw.
  3. When the diff comes back, record the artifact reference (commit SHA or file path) and run the evidence command.
  4. Record the review outcome with one line of reasoning, and the next slice.
  5. Commit the entry in the same pull request as the code, or immediately after a rejection.

Step 5 matters more than it looks. Reviewing AI-generated code works best when reviewers treat diffs as drafts and check them against the original intent, which requires the intent to be written down somewhere alongside the diff. A benchmark dataset cited in that review found that AI-assisted pull requests are notably larger than unassisted ones and have a far lower 30-day acceptance rate, which is precisely the pattern that a log of rejected tasks helps you diagnose.

For multi-step work, write the log at the granularity of the slice, not the epic. Splitting work into small vertical slices is a long-standing practice in story splitting, and the same logic applies to agent tasks: a slice is small enough to review in one sitting and to describe in one log entry per the Humanizing Work guide. If an entry needs three paragraphs of context to make sense, the task was too big.

Loading past entries at the start of a session

The loading step is where the log pays for itself. Do it before the agent touches anything, and keep it to the last three to five entries plus the spec reference.

A simple, portable opener:

Read docs/tasks/index.jsonl and docs/specs/<feature>.md before doing anything.

From the log, summarize in at most 10 lines:
1. What is already shipped for this feature (task IDs and commits).
2. What was rejected and why.
3. Open constraints discovered along the way.
Do not restate the full caveats. Wait for my next instruction.

Three details make this work. First, it forces a summarization step before action, which is the same idea as context folding, where a sub-trajectory is collapsed into a concise summary of the outcome while preserving progress as described in the Context Folding work. Second, it scopes the read: the agent reads the log and the spec, not the whole repository and every past transcript. Third, it asks for the rejected tasks by name, because that is the information a fresh session never has and most needs.

For debugging, a structured entry with the prompt and evidence makes a natural trace record. Agent observability tooling built on OpenTelemetry conventions captures tool calls, tokens and costs, and open-source tools visualize those traces for agents in production. A task log is the human-readable companion to that: the trace tells you what the agent did in one run, the log tells you what was decided across runs.

If you are running many agents on one codebase, the same opener works with one change: add "read only entries whose spec_ref matches this area." That keeps each agent's context small and relevant, which is the whole point.

Handoffs between people and agents

A handoff is the log's hardest test. The incoming person may be a colleague, a contractor, or a different agent with a different harness. They all need the same thing: what was asked, what shipped, what failed and why.

Before handing off, do four things:

  • Update the index file with a one-line status per open task.
  • Make sure every accepted task has an artifact reference that resolves (commit SHA exists, tests are green on that commit).
  • Make sure every rejected task has a reasoning line that states the constraint discovered, not just the verdict.
  • Add a known-issues section to the spec with anything the log revealed but did not fix.

For the incoming side, the opening prompt is the same as above, plus one line: "List any open questions that the log does not answer, before suggesting work." That line surfaces gaps cheaply. If the log cannot answer "does the retry logic apply to 4xx," the incoming session asks rather than guesses, and the answer goes into the log.

If your handoffs cross model providers, keep the log format provider-neutral. Plain JSONL with no model-specific fields in required positions means the same entry feeds an agent on any harness, which is the practical argument for keeping the exact prompt in a file rather than buried in a tool-specific session store. If your work spans several providers, putting them behind a single OpenAI-compatible endpoint with one key, as Quanta Inference does, keeps the log's model and cost fields consistent across tasks and makes the acceptance-rate comparison fair.

Reading the log for patterns after a week of tasks

The log turns into something more useful than a record once you have 20 or 30 entries: a dataset about your own agent workflow.

Three queries are worth running by hand or with a small script:

Acceptance rate by prompt template. Group entries by which prompt file or template they used and count accepted plus accepted-with-edits against the total. A template with a low rate is usually missing a constraint that appears in the reasoning of its rejections.

Edits per accepted diff. If most accepted work needed edits, your specs are underspecified, not your agent. The spec-first literature is consistent on this: alignment work done before implementation reduces downstream rework according to Microsoft's practical lessons.

Rejection reasons clustered by type. Sort the reasoning lines into buckets like scope, correctness, missing constraint and test failure. The largest bucket names the fix.

The decisive signal is the shape of the work rather than the count. If rejections cluster around scope (the agent changed files beyond the task), tighten the spec's boundary section. If they cluster around correctness on multi-file edits, the task is too large for one slice and needs splitting. Structure is what makes agent work predictable; JetBrains' spec-driven guide argues the same thing with a requirements, plan and task-list sequence written to files that survive the conversation step by step. The task log is the fourth file in that sequence: the record of what actually happened when the plan met the code.

FAQ

FAQ

How much detail should a log entry carry?

Enough that a reader who has never seen the task can tell what was asked, what was produced and why it was accepted or rejected. In practice that is a short request line, a prompt file reference, a commit SHA or output path, one evidence line and one reasoning line. If the entry needs more than that, the task should have been split.

Should I log tasks the agent failed or that we abandoned?

Yes, and these are often the most valuable entries. Rejected tasks record the constraints you discovered the hard way, and a fresh session has no other way to learn them. Log the reasoning line, not just the verdict, so the next attempt starts from the discovered constraint.

Can the agent write the log itself?

It can draft the entry, and you should still review it. The risk is that an agent summarizes its own work as successful, and the artifact reference plus evidence line are exactly the fields that must be checked against reality. Have the agent append a draft, then confirm the artifact and evidence before committing.

Does this work for non-code agent work?

Yes. Replace the diff with whatever the output artifact is (a document path, a spreadsheet, a generated image set) and replace the test command with the check you actually ran. The four core fields stay the same: task ID, exact prompt, output, review outcome.

What if the log gets too large to load?

Never load all of it. Keep a small index file with the last few tasks and open-task status, and have the agent read only entries whose spec reference matches the current area. That keeps the working context small and relevant, which is the same reason long-running agents are built to fold completed subtasks into short summaries.

Sources

Sources

  1. Components of A Coding Agent - by Sebastian Raschka, PhD
  2. Learning Agent-Compatible Context Management for Long-Horizon Tasks
  3. Long-Horizon Planning and Goal Decomposition in AI Agents
  4. A Spec-First Approach to AI-Native Engineering - Microsoft Developer
  5. Best Practices for Prompts in AI Agent Studio | fusioncoe
  6. Code review best practices for AI-generated diffs
  7. The Humanizing Work Guide to Splitting User Stories
  8. Scaling Long-Horizon Agent via Context Folding - ICML 2026
  9. How To Debug AI Agents: Tracing, Observability & Evals
  10. How to Use a Spec-Driven Approach for Coding with AI
About the author

About the author

Antonio Evans
Antonio Evans

Antonio Evans is the founder of Quanta Intelligence and a fractional CTO who builds HIPAA-ready AI systems for health and life-science companies. Before that he was technical co-founder of FriendsEAT for twenty years, CEO of Socialdraft, and a data engineer at IBM. Antonio lives with his dog Santino in Lisbon, Portugal.

All articles