ealeng
Menu

Episode 06 of 25 · Context engineering

Long agent sessions and skills

A coding agent keeps adding to its own prompt, and 96% of it is tool output. Four ways to compact it against none, tested by asking the agent about its own task; why a careful structured summary lost the next step; and skills, instructions that load only when a request needs them.

Lab 07 · Context Engineering7 min read
Video transcript5:48

0:00Cold open

0:01

Our coding agent found a retry bug, fixed it, ran the tests, and wrote down its next step.

0:07

To save room, its older messages were replaced by a careful, structured summary. Then I asked: what’s your next step?

0:14

It named a different step. The real plan, update a config file, was gone.

0:20

The summary was told to include a next step. So where did it go?

0:25Intro

0:26

Hands-on AI engineering: context engineering, part two.

0:31

Today: long agent sessions, compaction, and skills, which load know-how only when it’s needed.

0:38Lina again

0:39

I’m Lina. Last time, the prompt was a budget. This time, an agent that works for a long time, and keeps adding to its own prompt.

0:48

This work log is made up for the test. The answers you’ll see are real: recorded runs of a small OpenAI model, gpt-5.4-nano.

0:58

Sixteen messages in, ninety-six percent of the agent’s context, everything the model reads on each call, is tool output: a log dump, a whole source file, test results, metrics.

1:11

Each one mattered for a single step, and then just sat there, sent again on every call. Compaction replaces those older messages with something shorter.

1:2101 · Testing a compaction

1:22

How do you know a compaction kept what matters? I keep the last four messages, and compact everything older.

1:29

Then I ask the agent seven questions about its own task: the user’s rule, the root cause, the exact file and line, the files it changed, the failing tests, its next step, and one number.

1:41

Each answer counts only with the exact detail. The number, an error rate of fourteen point two percent, was one line inside that log dump.

1:5102 · Five ways to compact

1:53

Without compaction, the agent answers all seven. That’s sixty-five hundred tokens, the word pieces models read and charge for, and growing.

2:02

Drop the older messages, and the agent forgets its own task. Its one check mark was a false pass: it said I don’t know, but quoted the backoff fix from the last messages.

2:14

Clear only the tool output, and keep the agent’s own messages: five of seven, with no extra AI call. It lost the test names and the number, which only lived in tool output.

2:26

A generic summary, one paragraph: three of seven. It kept the story, and dropped the details an agent needs to carry on: the line number, the files, the test names.

2:37

A structured summary, with named sections: goal, rules, findings, changes, current state, next step. Also five of seven, at about the same size, for one extra AI call. But it’s the only one that lost the next step.

2:5403 · Where the next step went

2:55

So why did it lose the next step? Look at what it wrote. It was told to drop raw logs. It copied example log lines anyway.

3:03

Then it hit the four-hundred-token output limit it was given, in the middle of the list of changed files. The current state and the next step were never written.

3:13

And the error rate, fourteen point two percent, was lost by every compaction method. It was one line in a ninety-one-line log dump, and no one ever wrote it down as a finding.

3:25

So I’d give the summary more room, have the agent write down findings as it goes, and test every compaction by asking the agent about its own task.

3:3604 · Skills

3:37

The other thing that piles up in an agent’s prompt is instructions: how to review SQL, how to write a postmortem, how to answer a customer.

3:46

A skill packages one of those: a name, a one-line description, and the full instructions. Our assistant has six.

3:54

Only the descriptions stay in the prompt: a hundred and fifty-one tokens, instead of about thirteen hundred for all six in full. When a request matches, that one skill is loaded.

4:0505 · Picking the skill

4:07

But the right skill has to get picked, and the model sees only names and descriptions. Fourteen test requests.

4:14

With good descriptions, fourteen of fourteen. With vague ones, like database stuff, still fourteen: names like sql review gave the answer away.

4:25

Then I kept the vague descriptions, and swapped the names for code names, like falcon. Seven of fourteen. A SQL review went to the Python reviewer.

4:35

So a description has to say when to use the skill, in the words users actually use.

4:4106 · Does it change the answer?

4:42

And does loading it change the answer? Each skill asks for a fixed format that a script can check. The SQL skill wants a verdict line. With no skill, only two of twelve passed, and both were emails, which start with a subject line anyway.

4:57

With the right skill loaded on demand: twelve of twelve.

5:01

Loading all six, all the time, also got twelve, at almost three times the tokens. With six small skills, that’s affordable. With fifty, it adds up on every request.

5:1307 · What I do now

5:15

So now: I clear old tool output first. When I summarize, I use named sections, and give the summary room to finish. And the agent writes down findings as it goes.

5:26

I test every compaction by asking the agent about its own task. And every skill gets a description that says when to use it.Lina: Test what the agent still knows. ✅

5:35Summary

5:36

Clear tool output. Summarize in sections. Test what it remembers. Load skills when needed.

5:42

Then a long session doesn’t mean a forgetful agent.Lina: Thanks! 😄

Key takeaways

  • ✓Sixteen messages into a debugging session, 96% of the agent's context was tool output: each piece mattered for one step, then was re-sent on every call.
  • ✓Test a compaction by asking the agent about its own task, and count an answer only with the exact detail: the rule, the file and line, the files changed, the test names, the next step, a number.
  • ✓Clearing old tool output (no extra call) and a structured summary (one call) both kept 5 of 7. A generic paragraph kept 3; dropping older messages kept none, apart from a false pass.
  • ✓The structured summary copied raw log lines it was told to drop, hit its 400-token limit mid-list, and never wrote its current state or next step. The one-line error rate was lost by every method.
  • ✓Skills keep only names and descriptions in the prompt (151 tokens instead of 1,258). The description decides the pick: vague descriptions with code names picked right 7 of 14. Loaded, a skill's format was followed 12 of 12 times, against 2 of 12 without.

An agent that works for a long time keeps adding to its own prompt: every tool result stays there, re-sent on every call. Compaction replaces the older part with something shorter, and the risk is that it drops what the agent still needs. This chapter compares four ways to compact against none, tested by asking the agent about its own task, then covers skills: instructions that load only when a request needs them.

The sources are ai-eng-labs Lab 07, scripts 3 (03_compaction.py) and 5 (05_skills.py). The agent's work log, the skills and the requests are made up; the answers are real recorded runs of gpt-5.4-nano, one run per test. Chapter 5 covers the prompt budget and huge tool output.

What fills an agent's context

A scripted debugging session. The user asks why payment webhook retries are hammering a partner API, and says not to touch the migrations/ folder. The agent reads the logs, reads retry.py, finds BACKOFF_MULTIPLIER = 0 on line 88, sets it to 2, adds a regression test, runs the suite (two retry tests still fail, because config/queues.yaml still says 3), and checks staging metrics.

Sixteen messages, 6,456 tokens: tool output is 6,225 of them (96%): a log dump, a whole source file, test results, metrics. Each mattered for one step, then sat there, sent again on every call. Compaction replaces older messages with something shorter.

Try it · Keep a long session shortReal recorded replies · gpt-5.4-nano · one run each

The agent's work log: 16 messages, 6,456 tokens · tool output 96%

■ tool output · ■ user · ■ agent. The last 4 messages are kept as they are; everything older is compacted.

Named sections: goal, rules, findings, changes, current state, next step (max_tokens = 400). The only method that lost the next step.

Context tokens
1,880
Questions right
5/7
Extra model calls
1
  • ✓Is there any folder I told you not to change? rule“Yes — you told me not to touch anything in the `migrations/` folder (another team owns it).”
  • ✓What was the root cause of the retry storm? root cause“The retry storm was caused by the backoff logic being effectively disabled: - In `retry.py` at line 88, `BACKOFF_MULTIPLIER = 0 # TODO tune`. - That makes `next_delay(attempt: int)` compute `BASE_DELAY * (0 attempt)`, which yields ~`BASE_DELAY` for attempt 0 and then effectively no meaningful backoff for subsequent attempts (so retries fire immediately). - Webhook worker logs reflected this with repeated retries showing `status=503` and `delay_ms=0` / very small”
  • ✓In which file and on which line was the bug? exact spot“The bug was in `retry.py`, on line 88: - `retry.py` line 88: `BACKOFF_MULTIPLIER = 0 # TODO tune`”
  • ✓Which files have you changed so far? files changed“So far, I changed these files: - `retry.py` (line 88): updated `BACKOFF_MULTIPLIER` from `0` to `2` - `tests/test_retry.py`: updated/adjusted retry-related tests (to match the expected backoff/max-attempts behavior)”
  • ✓Which tests are still failing? Give their names. failing tests“I don’t know which tests are still failing from the log you provided. The only test failures mentioned earlier were: - `tests/test_retry.py::test_dead_letter_after_max_attempts` - `tests/test_retry.py::test_max_attempts_config`”
  • ✕What's your next step? next step“Next step: verify the fix end-to-end by re-checking staging webhook-worker retry behavior (delay_ms/backoff and max-attempt/dead-letter counts) and confirm the partner API is no longer being hammered—i.e., look for retries spreading out and dead-letter happening at the expected attempt threshold (8, not 3).”
  • ✕What was the webhook error rate before the fix? a number“I don’t know the webhook error rate before the fix from the log you provided. The only staging error-rate data shown is after the backoff change (summary: 0.8%).”

What the compaction wrote

- Goal: what the user asked for  
  - Find out why Payments webhook retries are hammering the partner API.

- Rules from the user: anything they said to do or not do  
  - Don’t touch anything in the migrations/ folder (another team owns it).

- Findings: what was discovered, with exact locations and values  
  - `retry.py` line 88: `BACKOFF_MULTIPLIER = 0  # TODO tune`  
    - This causes `next_delay(attempt: int)` to return `BASE_DELAY * (0 ** attempt)`, resulting in effectively no backoff (retries fire immediately).
  - Webhook worker logs show rapid repeated retries with `status=503` and `delay_ms=0` / very small delays:
    - Example: `2026-03-09T14:10:05Z ... retry attempt=1 ... delay_ms=0 status=503`
    - Example: `2026-03-09T14:10:25Z ... retry attempt=2 ... delay_ms=0 status=503`
    - Example: `2026-03-09T14:12:05Z ... retry attempt=2 ... delay_ms=3 status=503`
  - Test failures indicate dead-letter/max-attempts behavior is still configured to 3:
    - `tests/test_retry.py::test_dead_letter_after_max_attempts` failed: expected dead-letter after 8 attempts, found after 3
    - `tests/test_retry.py::test_max_attempts_config` failed: expected `max_attempts == 8`, found `max_attempts == 3`

- Changes made: every file changed and how  
  - `retry.py`  
    - Updated `BACKOFF_MULTIPLIER` at line 88 from `0` to `2` to enable non-zero backoff between retries.
  - `tests/test_retry.py`
✂ hit its 400-token limit here: “Current state” and “Next step” were never written

It was told to drop raw logs, and copied three log lines anyway. The 14.2% error rate was one line in a 91-line log dump: every method lost it.

Testing a compaction

Keep the last 4 messages, compact everything older, then ask the agent seven questions about its own task. An answer counts only with the exact detail:

Needs Question Must contain
Rule Is there any folder I told you not to change? migrations
Root cause What was the root cause of the retry storm? backoff
Exact spot In which file and on which line was the bug? retry.py, 88
Files changed Which files have you changed so far? retry.py, test_retry.py
Failing tests Which tests are still failing? Give their names. both test names
Next step What's your next step? queues.yaml
A number What was the webhook error rate before the fix? 14.2

The number, an error rate of 14.2%, was one line inside a 91-line log dump.

Five ways to compact

Method Context tokens Right (of 7) Extra model call What it lost
No compaction 6,522, and growing 7 No Nothing
Drop older messages 1,474 1, a false pass No Its own task
Clear tool output 1,734 5 No The test names and the 14.2%, which only lived in tool output
Generic summary 1,645 3 Yes The line number, the files, the test names, the 14.2%
Structured summary 1,880 5 Yes The next step and the 14.2%

(6,522 includes the role labels and wrappers around the 6,456 tokens of messages.)

  • Dropping older messages, the agent forgets its own task. Its one ✓ is a false pass: "I don't know from the log you provided… mentions a 'backoff fix'", and the grader only looks for "backoff".
  • Clearing old tool output keeps the agent's own messages, where it wrote down its findings, with no extra AI call.
  • A generic summary ("Summarize this conversation… in a short paragraph") kept the story and dropped the details an agent needs to carry on.
  • A structured summary has named sections: goal, rules from the user, findings, changes made, current state, next step, keeping names, paths, line numbers and numbers exactly. Also 5 of 7, at about the same size as clearing tool output, for one extra call. And it's the only method that lost the next step.

The lab's grader is lenient in one more place: the structured summary's "failing tests" answer opens with "I don't know which tests are still failing", then lists both names, and counts as right. The practice writes a stricter grader.

Where the next step went

Read what the structured summary wrote. Its prompt said "Drop raw logs, file contents, and tool output once their findings are recorded above." It copied three example log lines anyway. Then it hit the 400-token output limit it was given (396 tokens) in the middle of the list of changed files, ending at "- tests/test_retry.py". "Current state" and "Next step" were never written. The plan, update config/queues.yaml, was gone; asked for its next step, the agent named a different one.

And the 14.2% was lost by every method: one line in a log dump, and no message ever wrote it down as a finding.

What to do about it (the lab didn't rerun with a bigger cap, so this is reasoning, not a measurement): give the summary room to finish and check that every section is there, have the agent write down findings as it goes, and test every compaction by asking the agent about its own task. On gpt-5.4-mini, the lab notes structured compaction kept 6 of 7.

Skills: know-how on demand

The other thing that piles up in an agent's prompt is instructions: how to review SQL, write a postmortem, answer a customer. A skill packages one: a name, a one-line description, and full instructions (a SKILL.md file, plus any scripts). Only the names and descriptions stay in the prompt; when a request matches, that skill's instructions load.

The assistant has six skills: api-design-review, customer-email, incident-postmortem, python-code-review, release-notes, sql-review. Their descriptions cost 151 tokens; all six in full, 1,258.

Does the right skill get picked? 14 test requests (12 need a skill, 2 need none):

Descriptions Picked right
Good: "Use when reviewing, checking, or optimizing a SQL query someone wrote…" 14/14
Vague: "Database stuff.", "Code helper." 14/14, because names like sql-review gave it away
Vague, with code names (atlas, falcon…) 7/14: both SQL reviews went to the Python reviewer, the postmortems to release notes and API review

A description has to say when to use the skill, in the words users actually use. (On gpt-5.4-mini, even good descriptions missed once: "Thoughts on this?" plus some code picked no skill, because the user never said "review".)

Does loading it change the answer? Each skill requires a format a script can check, like a Verdict: line or an ## Incident summary heading:

Setup Format followed Tokens per request
No skill 2/12: both customer emails, which start with "Subject:" anyway ~39
The right skill, loaded on demand 12/12 ~504
All six, always loaded 12/12 ~1,371 (2.7×)

With six small skills, loading them all is affordable. With fifty, it adds up on every request.

The checklist

  1. Clear old tool output first: it's most of the context and costs no model call.
  2. Summarize in named sections, with room to finish, and check every section is there.
  3. Have the agent write findings down as it goes, so they don't live only in tool output.
  4. Test every compaction with questions about the agent's own task, graded on exact details, and read the passes too.
  5. Give every skill a description that says when to use it, and measure the pick rate whenever a description changes.

Practice: compaction and skills

Clear old tool output without touching the agent's own messages, check a structured summary for missing sections (the real one is missing two), write a grader that rejects the false pass, build the skills listing, and measure pick rates. The tests use the real work log, the recorded structured summary and replies, and the lab's 14 requests.

Try it · Practice in PythonRuns in your browser · ⌘/Ctrl + Enter to run
session_practice.py64 lines

Quiz

Try it · Check your understanding0 of 6 answered
  1. 1.Sixteen messages in, what filled most of the agent's context?

  2. 2.How does the lab check whether a compaction kept what matters?

  3. 3.Dropping older messages scored 1 of 7. What was the one?

  4. 4.Clearing old tool output kept 5 of 7 with no extra model call. What did it lose?

  5. 5.Why did the structured summary lose the next step?

  6. 6.With vague descriptions, skill picks were still 14 of 14. Why did they drop to 7 of 14 with code names?

Check your understanding

Try each question before opening its answer.

What makes up most of a long agent session's context?

Tool output: here 96% (6,225 of 6,456 tokens), from a log dump, a source file, test results and metrics. Each piece mattered for one step and was then re-sent on every call.

How do you test a compaction?

Compact everything but the last few messages, then ask the agent questions about its own task (the rule, the root cause, the exact spot, the files changed, the failing tests, the next step, a key number) and count an answer only with the exact detail. Compare with no compaction.

Clearing tool output vs. a structured summary: which would you start with?

Clearing old tool output: it kept 5 of 7 with no extra model call, about the same as the structured summary (5 of 7, one call). It loses only what never left the tool output, so pair it with an agent that writes findings down.

Why did the structured summary lose the next step?

It spent its room copying raw log lines it was told to drop, hit its 400-token limit mid-list, and never wrote "Current state" or "Next step". Give the summary room, check its sections, and record findings as you go.

What decides whether a skill gets used?

Its name and description, because that's all the model sees when picking. Vague descriptions worked only while the names gave the answer away; with code names, picks fell to 7 of 14. Say when to use the skill, in the users' words.

Why load skills on demand rather than all at once?

Both followed the format 12 of 12 times, but loading all six cost about 2.7 times the tokens on every request (~1,371 vs. ~504). That gap grows with every skill you add.

Next up: Chapter 7 turns text into embeddings and tests when a search score points to the wrong help-center answer.

Learning something useful?

New labs, articles, and videos on evaluating and testing AI systems come out regularly. Follow along so you don't miss the next one.