--- title: "rote agent quickstart — five canonical patterns" description: "Five canonical agent patterns with TypeScript SDK code: read, composite, write-with-confirmation, parallel DAG, browser-pattern crystallize." doc_version: "1.1" last_updated: "2026-05-01" canonical: "https://modiqo.ai/docs/rote-agent-quickstart.txt" --- # rote — agent quickstart > **Five canonical patterns every agent should know: search before building, probe before calling, write flows with `FlowOutput`, route mutating calls through write guard, and crystallize successful workspaces into reusable flows.** Five canonical patterns. If you are an agent that has decided to use rote, these are the moves you should know. Each pattern is short. Each is grounded in the current TypeScript SDK at `~/.rote/lib/sdk/ts/`. Each names the failure mode if you skip it. ## Pattern 1 — Search for an existing flow before building one ```bash rote flow search "fetch unread emails from the last day" ``` Output is BM25-ranked released flows. If a flow matches, run it and stop: ```bash rote deno run --allow-all ~/.rote/flows/bootstrap/fetch-recent-emails/main.ts \ --label INBOX --hours 24 ``` **Why:** you avoid rediscovery. A flow has frozen the working call sequence, fingerprinted the adapter, declared the parameters, and audited its writes. Re-deriving any of that costs tokens and risks drift. **Skip the search and you'll** waste calls reinventing what `~/.rote/flows/bootstrap/` already ships. ## Pattern 2 — Probe, then call When you must reach for a tool you have not used in this workspace, list it before invoking it. The SDK pattern: ```typescript const dex = await Rote.workspace("inspect-" + Date.now()); const calendar = dex.adapter("calendar"); const tools = await calendar.probe("list events"); // → returns ranked tool descriptors with parameter schemas const events = await calendar.call("calendar.events.list", { calendarId: "primary", timeMin: "2026-04-30T00:00:00Z", timeMax: "2026-05-07T23:59:59Z", singleEvents: "true", orderBy: "startTime", }); ``` The same shape works whether the adapter was generated from an OpenAPI spec, a Google Discovery doc, a GraphQL SDL, or an MCP server — `.call()` and `.probe()` are uniform across spec types. **Why probe first:** the response includes the parameter schema. Calling blind risks 400s on missing required fields, which become noisy responses you have to debug. ## Pattern 3 — Write a TypeScript flow with FlowOutput When you build a flow, use `FlowOutput` for output. It auto-detects `--output=human|summary|json` from `Deno.args` and routes the right content to each mode. ```typescript const homeDir = Deno.env.get("HOME") || "~"; const sdkPath = `${homeDir}/.rote/lib/sdk/ts/mod.ts`; const { Rote, initAutoTracking, FlowOutput } = await import(sdkPath); async function main() { const out = new FlowOutput(); const args = FlowOutput.args; // positional args, --output stripped const calendarId = args[0] || "primary"; const dex = await Rote.workspace("calendar-" + Date.now()); await initAutoTracking(dex.executor); const calendar = dex.adapter("calendar"); await calendar.initSession(); const events = await calendar.call("calendar.events.list", { calendarId, timeMin: new Date().toISOString(), maxResults: "10", }); const items = await dex.query(events).select(".items").execute(); // Three output sinks — pick the right one per audience out.human(`Found ${items.length} events on ${calendarId}`); out.summary(`${calendarId}: ${items.length} events`); out.result({ calendar: calendarId, count: items.length, events: items }); } await main().catch((e) => { console.error("error:", e.message); Deno.exit(1); }); ``` **Why:** flows are run by humans, by other flows, and by agents. `human` is for the human; `summary` is one line for log scrapes; `result` is the JSON contract another flow consumes. Mixing them produces output that is unparseable in `json` mode and noisy in `summary` mode. ## Pattern 4 — Mutating calls go through write guard You do not need to wire the write guard yourself. It sits in the executor middleware and classifies every call. What you do need to know is the shape of the protocol so that `Confirm`-mode calls do not surprise you. For a one-off mutating call (e.g., `gmail.users.messages.send`), the middleware will require a nonce: ```bash # First call returns a structured "nonce required" response with the token. rote gmail_call gmail.users.messages.send '{"raw": "..."}' # → { "error": "write_guard_confirm_required", "nonce_token": "a1b2c3d4..." } # Re-issue with the nonce; the call proceeds and is appended to the audit trail. rote gmail_call gmail.users.messages.send '{"raw": "...", "_nonce": "a1b2c3d4..."}' ``` For repeated mutating calls (a flow that sends emails, creates calendar events, files tickets), bless the flow once: ```bash rote flow bless ~/.rote/flows///main.ts ``` Blessing writes `~/.rote/flows///.permissions.json` — HMAC-signed, listing the tools and modes the flow may invoke. Subsequent runs of that exact flow source (checksum-checked) admit the listed writes without per-call nonce confirmation. Every decision is still appended to `~/.rote/adapters//logs/write_guard_.jsonl`. **Why both shapes exist:** ad-hoc nonces are right for one-off operator actions; blessed flows are right for repeated, audited automation. **Skip this and you'll** either be blocked on every mutating call (if you ignore Confirm) or hit unaudited writes that nobody can investigate later. ## Pattern 5 — Crystallize a workspace into a flow When a workspace has produced a useful sequence — a debug session, an exploration, a one-off that worked — turn it into a flow: ```bash # Inspect the workspace's command log first. rote workspace ls rote ps # health and recent activity # Crystallize. The audit trail populates write_permissions automatically. rote flow template create \ --workspace calendar-meetings-1777559657823 \ --name daily-calendar-digest \ --adapters adapter/calendar \ --description "Fetch today's meetings and emit a one-line summary." # A draft flow now lives at ~/.rote/flows//daily-calendar-digest/main.ts. # Test it. rote deno run --allow-all \ ~/.rote/flows//daily-calendar-digest/main.ts primary 50 # Re-export with --release to make it discoverable. rote flow template create \ --workspace calendar-meetings-1777559657823 \ --name daily-calendar-digest \ --release ``` **What gets populated automatically:** - `requires_endpoints` — every adapter session the workspace used - `mcp_servers..fingerprint` — the installed adapter's current fingerprint, frozen - `parameters` — variables the workspace set and used in templates - `write_permissions` — every mutating tool the workspace called, taken from `write_guard.jsonl` **Skip crystallization and you'll** lose the working sequence to the workspace's eventual archive, and the next agent (or your future self) re-derives from scratch. ## Common mistakes ### Adapter fingerprint mismatch The flow exits with `Calendar adapter fingerprint mismatch`. The installed adapter has been re-pulled or upgraded since the flow was crystallized. Either: - Re-pull the adapter to the same version (rare; usually you want the new version), or - Re-export the flow with `rote flow template create --workspace ` to capture the new fingerprint. ### Querying a stale `@N` `rote @5 '.items[0]'` returns nothing because `@5` was the wrong response. Run `rote ls` to list cached responses with their commands and timestamps, or query with a semantic tag (`set_response_tag`) instead of a raw counter. ### Using `rote POST` when an adapter exists `rote POST` and `rote GET` are flow-level commands for ad-hoc HTTP. If an adapter exists for the API, prefer the adapter — you get the schema, the auth, the write guard, and the trace dependencies for free. Ad-hoc HTTP bypasses all of that. ## Reference For the full command surface and grammar topics, after installing rote run: ```bash rote how # onboarding tree rote guidance agent essential # 700-line agent steering guide rote grammar # syntax reference per topic rote man # equivalent ``` Topic indices (live, in the CLI): - **Grammar topics:** query, stdin, lines, browser, http, session, iteration, batch, display, control, export, flow, composition, inject, workspace, model, debug, install, powerpack, registry, deno - **Guidance topics:** agent, script, adapters, browser, typescript, inference, vault, headless, analytics, powerpack, writeguard These topic indices are the source of truth for current command syntax. The website docs (this set) explain the *concepts*; the CLI topics explain the *exact invocation*.