Concepts
Core concepts
Section titled “Core concepts”Addresses. An agent address is { kind: "agent", agentId, sessionId }. IDs
are 1 to 256 characters. There is no special kind for subagents.
Mail. A BirdDogMail has a stable key, a to and from address, a
replyTo list, string content and a createdAt time in milliseconds. The key
must identify the request across retries. BirdDog derives every reply key from
it.
Agent jobs. BirdDog.agentJob({ work, mail? }) validates the input and
returns a queued Watchdog job. The job’s queue is the target sessionId, its
lane is default, its priority is 0, and its payload carries the sessionId,
the commandFactId and the optional mail. work.recovery passes straight
through to Watchdog’s recovery policy. Because it is synchronous, you can call
it inside an owner transaction and pass the result to Watchdog’s
transactional.enqueueAcceptedJob. BirdDog.decodeAgentJob(job) parses the
payload back on the executor side. Watchdog never reads it.
Fan-out. fanOut({ job, content }) takes a settled job and the content owed
to correspondents. It writes one reply per replyTo address into the outbox,
keyed outbox:<mail key>:reply:<index>, then schedules one wake for the
earliest. Each reply starts with a small header, then your content:
---outcome: completedagentId: childsessionId: child-session---
A test fixture was missing. Fixed it.A completed job reports outcome: completed. A failed, outcome_unknown or
interrupted job reports outcome: interrupted. Cancellation is quiet: a
cancelled job sends no replies. A job without mail sends nothing.
Draining. drainOutbox() reads one page of up to 64 outbox rows and calls
post for each due reply. post returns true when the recipient accepts the
mail. A false or a throw schedules a retry. If more rows remain, BirdDog
schedules an immediate wake and continues from the same place on the next drain.
Receipts. A delivered reply’s row is replaced by a compact completion receipt under the same key. Replaying the same settlement after a restart finds the receipt and does not post the reply again. Keep those receipts as long as source settlements can replay. BirdDog does not expire them.
Host ports. BirdDog.make takes four things:
outbox: string rows withput,read, orderedlist(limit, afterKey?)anddelete.post(mail): delivers one reply and reports acceptance.scheduleWake(at): arms a durable timer fordrainOutbox.now(): the current time in milliseconds.