Skip to content

resource

Chapter 7 Plan: Durable Inbox and Outbox

Read the planned learning contract for durable inbox and outbox delivery in Chapter 7. Review prerequisites and proposed tasks; completed notebooks and solutions are not available yet.

Planned construction brief. The complete lesson, runnable notebooks and checkpoint are not available yet.

Status: PLANNED. This construction brief defines the new lesson and acceptance cases. Its full manuscript, learner implementation, two runnable notebooks and checkpoint remain to be authored. Existing Telegram and scheduling demonstrations continue to use supplied runtime infrastructure until their handoff is rebuilt against this chapter.

Why Lucy needs this chapter

A request stored in a Python list vanishes with the process. A completed stock brief can also vanish from the customer's perspective if the process dies between recording completion and sending the reply. These are different failures: the agent needs durable work to do and durable reports to deliver.

This chapter follows tested skills and precedes Telegram. We first build the shared work mechanism without a messaging account. Telegram and the scheduler then become producers for that mechanism rather than separate agents.

Goals and prerequisites

Bring the Chapter 4 state store, Chapter 5 session/context records and Chapter 6 active procedure. No queue, outbox, delivery-guarantee or state-machine knowledge is assumed. Introduce those ideas with paper records and a single worker before using their technical names.

By the end you will be able to:

  1. Persist a request under a stable source identity and explain exact duplicate versus conflicting duplicate.
  2. Admit or reject work before invoking a model, with explicit capacity and session rules.
  3. Claim one pending assignment and connect it to the existing learner-owned loop.
  4. Complete work and create its report in one transaction, so a committed completion cannot lose its report locally.
  5. Separate completed business work from confirmed, pending or uncertain outbound delivery.
  6. Explain which crash cases the single-worker introduction handles and which require Chapter 12's ownership recovery.

Concepts introduced from first use

An inbox is persisted input awaiting handling. A queue orders or selects work; it does not require a separate server. A state machine names allowed transitions so “pending,” “running” and “finished” cannot be arbitrary labels. A source identity names the external occurrence; a session identity groups conversations. Two messages with equal text can be separate occurrences, while one occurrence delivered twice must not become two jobs.

An outbox is a local record of an intended external report. It closes the gap between committing a result and remembering to send it. It does not make a database transaction extend across a network. If the recipient may have accepted a send before its reply disappeared, the outcome is UNKNOWN. A local retry cannot promise exactly-once external delivery unless the external service supplies and honors the required identity/reconciliation contract.

Derive these names from two failure experiments: restart an in-memory queue, then stop after completing work but before creating its report. Explain atomic state/report creation using the transaction built in Chapter 4. A SQL trigger may later express the same invariant; teach its implicit execution explicitly before replacing visible Python statements with it.

Build, fail and repair

StepBuildFailure made visible
1Admit a request into a Python listProcess restart loses it
2Persist identity, session, payload and pending stateRepeated intake must not create a second work item
3Compare a duplicate's immutable fieldsReused identity with different content is a conflict
4Add bounded admission and one atomic claimRefused work must not call the model or occupy ordinary capacity
5Route the claimed request through the existing loopA hardcoded report would conceal that learner code was never invoked
6Complete work, then separately insert a reportAn injected crash leaves a completed assignment with no report
7Put terminal state and report insertion in one transactionThe same crash leaves neither half committed
8Claim report delivery and retain confirmed or unknown dispositionA lost remote reply cannot silently become permission to resend

The first worker is deliberately single-process. Do not borrow the finished runtime's lease/generation implementation without teaching it. A crash while executing leaves a visible unresolved assignment; Chapter 12 adds fenced ownership, takeover and recovery. The initial lesson may refuse automatic replay rather than inventing a successful recovery.

Ownership and dependency interfaces

The learner owns admit(source_id, session_id, text), claim(worker_id), finish(work_id, result) and the outbox repository. These names describe proposed chapter interfaces, not existing finished helper imports. Inject the state store and the Chapter 3 loop so the data path can be observed directly.

Admission outcomes distinguish accepted, identical duplicate, conflicting duplicate and capacity refusal. A claim on an empty queue returns no assignment and performs no model call. Completion binds the result to the specific claimed work identity. Report identity is immutable and distinct from work identity: later recovery may produce a different terminal generation without rewriting an already issued report.

The sender boundary receives one retained report and returns a known receipt or an explicit uncertain outcome. The core lesson uses a controlled fake transport with an independent accepted-send log. Telegram's adapter in Chapter 8 supplies authenticated intake and its polling cursor, but may only acknowledge intake after the shared admission transaction commits. Chapter 9's clock/stock producers use the same admission contract.

Do not conflate authentication and deduplication. Knowing that an occurrence is new does not establish who authorized it. The adapter is responsible for authenticated identity; the queue retains it without allowing generated text to replace it.

Unit A — Construct and connect, 90 minutes

MinutesDedicated workSaved evidence
0–10Predict which requests survive a list-backed restartState sketch
10–25Build the work schema with source/session identitiesPersisted sample request
25–40Implement admission and distinguish duplicate/conflictAuthored dispositions
40–55Add bounded admission and single-worker claimEmpty/capacity/claim observations
55–75Connect the learner loop and atomically retain result/reportInput-to-result data trace
75–85Reopen the store and inspect the independent report rowDurable observation
85–90Explain the unresolved worker-crash caseRecall and handoff notes

Unit B — Diagnose and transfer, 90 minutes

MinutesDedicated workSaved evidence
0–10Predict crashes before and after commitExpected work/report states
10–25Reproduce the completed-without-report defectIndependent failure evidence
25–45Repair completion atomicity and propagate errorsBoth rollback and commit cases
45–60Simulate remote acceptance followed by a lost replyUNKNOWN plus independent accepted-send log
60–75Transfer to a second session, repeated input and rejected intakeNo duplicate work or unauthorized call
75–85Break the learner finish implementation deliberatelyChecker fails through the integrated path
85–90Explain why outbox persistence is not exactly-once networkingWritten answer

Independent acceptance examples

Given and actionExpected observation
Empty queue, one worker pollNo work and zero model invocations
Admit source s1 twice with identical session and textOne work record and a duplicate disposition
Reuse s1 with different textConflict; original text and state unchanged
Admit s2 with the same text as s1Two work records because occurrence identities differ
Fail between terminal state and report insertionReopen shows neither terminal change nor new report
Commit finish, then stop before sender runsOne completed work item and one pending report survive
Fake service accepts r1 but loses its responseOne externally accepted send, local UNKNOWN and no automatic second send
Second terminal generation legitimately creates r2Both immutable reports remain attributable to their own generation
Learner finish is replaced with a no-opThe integrated observer fails; supplied runtime cannot rescue the test

Completion requires the chapter's code to be consumed by Telegram and scheduling, not merely demonstrated beside them. Both notebook/Markdown pairs, worked answers, educator cases and the checkpoint must execute with learner-owned admission and completion.

Continue to Chapter 8: Telegram. Exercise Book · Solutions Book · Textbook contents.

Keep building with Prof Rod

Found this material through a colleague, classroom or shared download? Get the complete book at profrod.ai/book and join the Prof Rod learner community. Bring one result, one question or one failure you learned from. Share this resource with another learner and keep its source links with it so they can find the full course and future updates.

SOURCE PROVENANCE

Derived from github.com/profrodai/sovereign-agent/blob/5b825f3a58461bce8aba1173acf0b6d175c44b64/book/textbook/ch07/profrod-sovereign-agent-ch07-durable-inbox-outbox-chapter.md