/docs / workflows

Workflows

A workflow is work an employee does without being asked: a morning summary, a reply to each new message, a weekly report. Each workflow pairs a trigger with the activities the employee carries out. Workflows live in the employee's agent.json, so they travel with the role.

A first workflow

Add a workflows map to agent.json. Each key names a workflow; each value has a trigger and activities.

{
  "workflows": {
    "morning-summary": {
      "trigger": { "type": "schedule", "cron": "0 8 * * 1-5" },
      "description": "Summarize yesterday's open conversations every weekday morning.",
      "activities": [
        { "id": "summarize", "intent": "Summarize yesterday's open customer conversations and what each one is waiting on." }
      ]
    }
  }
}

This workflow runs at 08:00 on weekdays, in the bot's local time. The employee carries out the activity with its own persona, skills and connections.

Workflow fields

FieldMeaning
triggerRequired. When the workflow runs. See Triggers.
descriptionWhat the workflow is for.
activitiesThe steps. See Activities.
connectionsEdges {from, to, label} that make the activities a graph. __trigger__ is the start and __emit__ the end.
emitEvents this workflow announces when it finishes: a list, or one comma-separated string. See Events.
inputsValues passed to every run.
budget{total_per_run, cost_estimate}. In a graph run, total_per_run caps output tokens; otherwise both are estimates.
caseMakes the workflow one long-running case per person or thing. See Cases.

A workflow with a trigger and no activities is valid. A watch without activities only relays its events to other workflows.

How a run executes

Without connections, activities run in order and the employee performs each one. Each activity's result is passed to the next. An activity with no output ends the run.

With connections, the activities form a graph. Branches run in parallel, and six activity types run without the model: condition, loop, wait, http, command and decide. Use a graph when routing must be exact.

{
  "trigger": { "type": "watch", "plugin": "mail", "event": "email.new" },
  "activities": [
    { "id": "classify", "type": "decide",
      "params": {
        "questions": {
          "kind": {
            "type": "choice",
            "instructions": "What kind of message is this?",
            "criteria": { "invoice": "A bill from a vendor", "other": "Anything else" }
          }
        },
        "default": { "kind": "other" }
      } },
    { "id": "is-invoice", "type": "condition", "params": { "expression": "nodes.classify.kind.choice == invoice" } },
    { "id": "record", "intent": "Record the invoice in _watch_payload as a bill and note the due date." }
  ],
  "connections": [
    { "from": "__trigger__", "to": "classify" },
    { "from": "classify", "to": "is-invoice" },
    { "from": "is-invoice", "to": "record", "label": "True" },
    { "from": "record", "to": "__emit__" }
  ],
  "emit": ["invoice.recorded"]
}

What a run receives

The employee always has its persona and the owner's answers to its inputs questions. A run also receives these values, depending on its trigger.

InputPresent when
_event_source, _event_payload, _event_originAn event trigger fired. Payloads of 8 KB or more are shortened to their scalar fields, with email headers and attachment references kept.
_watch_payloadA watch or folder trigger fired. One line of the watcher’s output, or {files} for a folder.
inputsAlways. The workflow’s own inputs values.

Cases

Some work spans days: a lead that needs follow-ups, a request waiting on documents. Add case and the workflow keeps one open case per person or thing instead of starting fresh each time.

FieldMeaning
keyRequired. Comma-separated dotted paths into the trigger data that identify the subject, such as contactEmail,email,phone.
typeThe kind of case, such as lead. Workflows with the same type share cases. Defaults to the workflow name.
default_waitHow long to wait when a turn names no wait: 3d, 12h, 45m. Default three days.

Each turn of a case must end with one JSON object and nothing after it. result is the business state; next tells the engine to wait or close. A deadline is RFC 3339 or a relative span. Anything else is an invalid turn.

{"result": {"status": "awaiting_documents", "summary": "Requested two bank statements"},
 "next":   {"action": "wait", "on": "signal", "deadline": "3d", "reason": "documents"}}

Limits and recovery

  • Each activity can take up to 50 model turns, unless params.maxIterations says otherwise.
  • In a graph, one activity can run at most 10,000 times in a run.
  • The owner's spending cap for the employee stops a run when reached. An activity's token_budget is an estimate.
  • A run interrupted by a restart is marked interrupted and resumed once.
  • The employee can end a run early with the exit tool.

Run and manage workflows

The owner can run any workflow by hand. Employees manage workflows with run_workflow, workflow_status, list_workflow_runs, set_workflow_enabled and the other workflow tools listed on Helpers and Teams.