<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Harness from First Principles</title><id>https://build-an-agent.dasgupta-romit.workers.dev/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/"/><link rel="self" href="https://build-an-agent.dasgupta-romit.workers.dev/feed.xml"/><updated>2026-09-20T00:00:00Z</updated><author><name>Harness from First Principles</name></author>
  <entry><title>01 The function that forgets</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/01-the-function-that-forgets/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/01-the-function-that-forgets/"/><updated>2026-09-20T00:00:00Z</updated><summary>LLM APIs are stateless. Build chat memory from scratch in Python: a role-tagged message list you own and resend on every call. Runs in your browser.</summary></entry>
  <entry><title>02 Words are not deeds</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/02-words-are-not-deeds/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/02-words-are-not-deeds/"/><updated>2026-09-20T00:00:00Z</updated><summary>A model cannot read files or run code; it can only write. Build tool calls, tool results and call ids by hand and see what function calling really is.</summary></entry>
  <entry><title>03 Turn the crank</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/03-turn-the-crank/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/03-turn-the-crank/"/><updated>2026-09-20T00:00:00Z</updated><summary>An AI agent is a model call inside a while loop. Write the loop, learn why you continue on tool calls and not on stop_reason, test it with a fake model.</summary></entry>
  <entry><title>04 Tell the model what went wrong</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/04-tell-the-model-what-went-wrong/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/04-tell-the-model-what-went-wrong/"/><updated>2026-09-20T00:00:00Z</updated><summary>When a tool fails, the reader who can fix it is the model. Build the error boundary that turns exceptions into results an agent can recover from.</summary></entry>
  <entry><title>05 Knowing when to stop</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/05-knowing-when-to-stop/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/05-knowing-when-to-stop/"/><updated>2026-09-20T00:00:00Z</updated><summary>Agents loop forever and providers fail. Add max_turns and in-band error messages so every exit leaves a conversation you can safely continue.</summary></entry>
  <entry><title>06 The firehose</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/06-the-firehose/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/06-the-firehose/"/><updated>2026-09-20T00:00:00Z</updated><summary>Every tool result is re-sent and re-billed on every turn. Build head and tail truncation with byte budgets and notices that tell the model what to do next.</summary></entry>
  <entry><title>07 Show your work</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/07-show-your-work/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/07-show-your-work/"/><updated>2026-09-20T00:00:00Z</updated><summary>Stop printing from inside your agent loop. Turn it into a generator of events and drive a terminal, a JSON stream or any frontend from one loop.</summary></entry>
  <entry><title>08 Who holds the list?</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/08-who-holds-the-list/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/08-who-holds-the-list/"/><updated>2026-09-20T00:00:00Z</updated><summary>Two runs on one message list corrupt it. Build the harness object that owns the transcript and allows one writer at a time.</summary></entry>
  <entry><title>09 But I had something to say</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/09-but-i-had-something-to-say/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/09-but-i-had-something-to-say/"/><updated>2026-09-20T00:00:00Z</updated><summary>A user message can only land at two safe points in an agent run. Build steering and follow-up queues that never split a tool call from its result.</summary></entry>
  <entry><title>10 The poisoned transcript</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/10-the-poisoned-transcript/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/10-the-poisoned-transcript/"/><updated>2026-09-20T00:00:00Z</updated><summary>One interrupted tool call can brick a whole session with 400 errors. Build an idempotent repair that fixes what the model sees and keeps the record honest.</summary></entry>
  <entry><title>11 Pull the plug</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/11-pull-the-plug/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/11-pull-the-plug/"/><updated>2026-09-19T00:00:00Z</updated><summary>If the process dies mid-run, what does your agent remember? Build an append-only session log, resume by replay, and persistence as an event subscriber.</summary></entry>
  <entry><title>12 The wall</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/12-the-wall/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/12-the-wall/"/><updated>2026-09-19T00:00:00Z</updated><summary>When the prompt is too long, deleting old messages breaks the agent. Build compaction as a summary entry plus a replay rule, cut at a safe boundary.</summary></entry>
  <entry><title>13 The briefing</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/13-the-briefing/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/13-the-briefing/"/><updated>2026-09-20T00:00:00Z</updated><summary>A hand-written system prompt lies the moment your tools change. Compute it from tools, project files and a skills index that loads on demand.</summary></entry>
  <entry><title>14 The veto</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/14-the-veto/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/14-the-veto/"/><updated>2026-09-20T00:00:00Z</updated><summary>A file your agent reads can give it orders. See why the system prompt cannot save you, then build a fail-closed permission gate around your tools.</summary></entry>
  <entry><title>15 The stop button that does not stop</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/15-the-stop-button-that-does-not-stop/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/15-the-stop-button-that-does-not-stop/"/><updated>2026-09-20T00:00:00Z</updated><summary>A cancel flag stops nothing until slow code looks at it. Convert your agent to asyncio and build cooperative cancellation with a hard-stop backstop.</summary></entry>
  <entry><title>16 Capstone: out of the browser</title><id>https://build-an-agent.dasgupta-romit.workers.dev/lessons/16-out-of-the-browser/</id><link href="https://build-an-agent.dasgupta-romit.workers.dev/lessons/16-out-of-the-browser/"/><updated>2026-09-20T00:00:00Z</updated><summary>Write the adapter between your harness and a real provider: request translation, streaming SSE parsing, fragmented tool-call JSON. Then run it locally.</summary></entry>
</feed>
