Quickstart
Quickstart
Durable addressed agent mail over generic Watchdog work
This sends work from a parent agent to a child agent, settles it, and delivers
the reply. The outbox uses Carrier’s deterministic memory helper, and post
prints the reply instead of sending it anywhere.
import { BirdDog, type BirdDogMail } from "@fungi.computer/bird-dog";import { createMemoryOutbox } from "@fungi.computer/carrier/testing";
const parent = { kind: "agent", agentId: "parent", sessionId: "parent-session",} as const;const child = { kind: "agent", agentId: "child", sessionId: "child-session",} as const;
const room = await BirdDog.make({ outbox: createMemoryOutbox(), post: async (mail: BirdDogMail) => { console.log(`to ${mail.to.agentId}:\n${mail.content}`); return true; // the recipient accepted it }, scheduleWake: async (at) => { console.log(`wake me at ${at}`); }, now: () => Date.now(),});
// 1. Turn accepted work into a Watchdog job. Hand this to Watchdog's ingest.const job = BirdDog.agentJob({ work: { jobId: "job-1", sessionId: child.sessionId, commandFactId: "command-1", }, mail: { key: "delegation-1", to: child, from: parent, replyTo: [parent], content: "Find out why the build is red", createdAt: Date.now(), },});
// 2. Your Watchdog executor decodes the payload and runs the child's work.const payload = BirdDog.decodeAgentJob(job);console.log(payload.work.commandFactId); // "command-1"
// 3. When Watchdog settles the job, queue the replies, then deliver them.await room.fanOut({ job: { ...job, state: "settled", outcome: "completed" }, content: "A test fixture was missing. Fixed it.",});await room.drainOutbox();In a real host, the settled job comes from Watchdog’s tick() result and
drainOutbox() runs from the wake you scheduled.