Skip to main content

Workstreams

A Workstream is a record of multi-step business work in motion — a campaign launch, a lead engine, a weekly report, a communication loop. One per business outcome. Each has a status, an ordered set of phases, attached resources (datasets, pages, jobs, experiments), and a chronological event log — a git-log-style record of what happened and what’s next. In your workspace, Workstreams live under Activity. As an agent takes on a multi-step job it opens a Workstream and keeps it current — advancing phases, logging what it did, and flipping status to awaiting_user when it needs you. You watch progress, read the event log, and pick up or hand work back from there. A Workstream can host Experiments that decide whether a change worked. A root workstream can also operate as a Strategy: attach campaign workstreams as direct child resources and read their one-level portfolio from the root ledger.

Concepts

  • Statusactive, awaiting_user (paused for input/approval), blocked (external blocker), completed.
  • Phases — ordered steps (brand-brief, landing-pages, …), each with its own status.
  • Event log — append short factual lines ("Brand brief drafted, sent for review", "Blocked: Google Ads admin access missing", "Next: build the landing pages"). This is how you and future agents read history and what remains.
  • Decisions — a workstream remembers a great deal of context: what was discussed, what was tried, what somebody suggested. A decision is the narrower thing the business actually committed to — a course, the reason it was chosen, and who authorized it — and it stays the standing course until a later decision explicitly replaces it. That distinction is what lets an agent picking the work up weeks later continue what you agreed rather than re-argue it, and it makes a change of course visible: reversing a decision records a new one naming the decision it supersedes. A decision does not need an external change behind it — approving an action records one, and so does an agent committing to a strategy that changes nothing outside Erdo, such as which audience a campaign targets. The full record — every decision, what executed, and what the evidence said afterwards — is searchable on its own surface.

Projects

Every Workstream lives in a project — the work context that groups related work and can grant project members access to attached resources. The organization remains the tenant and security boundary; selecting a project focuses project-owned lists rather than creating another tenant. Creating a workstream requires a project slug, so if you’re driving Erdo headlessly and don’t have one yet, create it first. Projects are referenced by slug, and project membership is managed in the app (there’s no programmatic member surface). Listing and creating projects is available on all three surfaces:
The MCP tools are erdo_list_projects and erdo_create_project; the REST mirrors are GET /v1/projects and POST /v1/projects (body: name, slug, optional description).

Arming the loop, the ledger, and resources

A workstream can be driven entirely by hand, or handed to Erdo’s reconciliation loop to run on its own cadence. Arming attaches that loop to one workstream with a budget envelope — a token spend cap and a daily escalation cap — so autonomous work can never spend or interrupt past a limit you set. Nothing runs autonomously until you arm it; how much the loop may change live, customer-facing state on its own is a separate control, the autonomy mode. Set the budget envelope on the workstream state (token_budget_millicents, escalation_budget_per_day) before or while arming. The ledger is the loop’s single source of truth, read in one call: the budget envelope, the workstream’s experiments and their recent observations, the judge calibration record and trust dial, the decisions currently in force, your steering notes, open attention items, and the allocator’s current recommendation. Current decisions arrive with the ledger rather than being something the loop has to go looking for, because a course you approved is only worth recording if the next pass reads it before it reasons — so the loop continues what is in force, and when it does want to change course it proposes a new decision naming the one it would replace. Attaching a resource records that a page, dataset, experiment, job, thread, or another workstream belongs to this workstream in a named role (its output, an input, evidence, something it monitors), so the ledger and event log show the full shape of the work.

Programmatic access

You can also create, drive, and observe Workstreams over MCP, the REST API, or the CLI — the same surface an agent uses internally. Everything is org-scoped and RBAC’d (read needs project view, writes need contribute), and Workstreams are referenced by slug, never UUID.
Workstreams (and the surfaces built on them — Experiments, Engine autonomy, the Attention feed) are rolling out gradually. Until they’re enabled for your workspace, these endpoints and tools return permission_denied (“workstreams are not enabled for this organization”) — contact us to get switched on.

CLI

arm accepts --interval <min>, --model <id>, and --timezone <tz>; the --token-budget (millicents) and --escalation-budget (per day) flags set the workstream’s envelope via the state update first, then arm. attach --type is one of page, dataset, heartbeat, experiment_run, thread, job, knowledge_object, approval, or workstream, and --rel is the relationship (output, input, evidence, monitoring, subject, parent, child, running), with optional --title and --phase. The CLI authenticates with your Erdo token and the active organization (erdo login, erdo org).

MCP tools

Identity and RBAC ride the request context, so a caller can only reach their own org’s work.

REST

Base URL https://api.erdo.ai. Authenticate with Authorization: Bearer <token> and select the org with X-Organization-ID. POST /v1/workstreams/:slug/arm takes optional interval_minutes, model, and timezone (set the budget envelope on the state first with PATCH /v1/workstreams/:slug/state). GET /v1/workstreams/:slug/ledger takes optional observations_per_experiment. POST /v1/workstreams/:slug/resources takes the resource type, id, relationship rel, and optional title and phase.