Skip to main content

When to Use This Cookbook

You’re building an AI agent (or any LLM-powered workflow) that should manage Brew automations without the dashboard UI. The Brew SDK exposes every authoring, lifecycle, and execution path through typed deterministic methods. AI authoring stays scoped to email body generation (brew.emails.generate({ prompt })); the rest of the surface (triggers, automation graphs, publish, fire) works on explicit shapes so the agent’s intent is always inspectable.

Mental Model

Brew has three primary entities the SDK works with: Each resource exposes list(query) for the collection and get(id) for one bare row. The id is a positional argument, and include is a detail-read option that embeds heavier fields: brew.automations.get(automationId, { include: 'graph,versions' }), brew.automations.runs.get(automationRunId, { include: 'logs' }). Passing an id as a list filter now returns 400. The full lifecycle: define trigger → mint email bodies → assemble automation graph → publish → fire → inspect executions.

Recipe 1: End-to-End Deterministic Flow

The canonical recipe. Define the trigger explicitly, mint the email bodies in parallel, then assemble and publish the graph.

Recipe 2: Reuse an Existing Trigger

When your codebase already wires a stable trigger id (auth, billing, or platform webhook), skip step 1 and reuse it across multiple automations:

Recipe 3: Discover Existing Email Bodies Before Authoring

brew.emails.list() returns every body already minted for the brand so the agent can reuse instead of re-generating duplicates:

Recipe 4: Fire a Trigger from Your Backend

After publishing, your application code calls brew.automations.triggers.fire whenever the real-world event happens. Always pass an idempotencyKey option so retries don’t double-fire. metadata is NOT accepted: the trigger payload carries everything the workflow runtime sees.
The idempotency key is a request option, not a body field. The fire answers 202 with a bare body, so the started runs are on fire.automationRunIds directly: the old { success, code, message, details } envelope is gone. Retries with the same key replay the original automationRunIds without starting new workflow runs, and answer 200 instead of 202. Read the whole fire back with brew.automations.triggerInstances.get(fire.triggerInstanceId).

Recipe 5: Test an Automation Against Synthetic Data

Use brew.automations.test to test-run an automation (no real mail is sent, sendEmail nodes simulate). The resulting run is recorded as a test-mode run you can inspect via brew.automations.runs.get(automationRunId, { include: 'logs' }) (pass include: 'logs' to attach the per-node logs[]).

Recipe 6: Edit a Published Automation Safely

Use brew.automations.patch({ automationId, nodes, connections }) to stage a new version of the graph deterministically, then a second patch({ published: true }) to promote it. (Lifecycle and graph edits can’t ride the same patch: published is mutually exclusive with field updates.) The previously-published row stays live until you publish the new version explicitly.

Error Matrix

Every method throws BrewApiError when the API answers with an error (auth, validation, business rules), and a BrewTransportError (BrewTimeoutError or BrewConnectionError) when no usable answer arrives — see Error handling. The error envelope carries code, type, message, suggestion, docs URL, and the offending param when relevant.

Determinism vs AI Authoring

Graph authoring here is deterministic: you supply the nodes, connections, and payload schema explicitly. AI is scoped to email body content only.

Need Help?

Our team is ready to support you at every step of your journey with Brew. Choose the option that works best for you:

Search Documentation

Type in the “Ask any question” search bar at the top left to instantly find relevant documentation pages.

ChatGPT/Claude Integration

Click “Open in ChatGPT” at the top right of any page to explore it further with ChatGPT or Claude.