Run a workflow

This guide creates a Workflow Agent that calls a person to confirm an appointment, and tries again if nobody answers. Then it starts one run and reads the result. Read Workflows first for the concepts.

Before you start

  • Complete Get access, and keep the terminal open.
  • Create an approved, active Call Agent for the confirmation call. Its input_schema must accept the values the workflow passes, such as patient_name and appointment_time. See Change what an agent says.
  • A run places real calls, and normal charges apply.

Create the Workflow Agent

read -r -p 'Call Agent id for the confirmation call: ' CALL_AGENT_ID

jq -n --arg agent "$CALL_AGENT_ID" '{
  name: "Confirm appointment",
  instructions: "Confirm the appointment for $patient_name at $appointment_time by calling $phone_number with the confirmation Call Agent. If nobody answers, wait at least two hours and try again. Stop after the patient confirms, cancels, or asks to reschedule.",
  input_schema: {
    type: "object",
    properties: {
      patient_name: {type: "string"},
      appointment_time: {type: "string"},
      phone_number: {type: "string"},
      timezone: {type: "string"}
    },
    required: ["patient_name", "appointment_time", "phone_number"],
    additionalProperties: false
  },
  analysis_prompt: "Record whether the patient confirmed, cancelled, or asked to reschedule, or whether nobody could be reached.",
  analysis_schema: {
    type: "object",
    properties: {
      outcome: {type: "string", enum: ["confirmed", "cancelled", "reschedule", "unreachable"]}
    },
    required: ["outcome"],
    additionalProperties: false
  },
  triggerable_call_agent_ids: [$agent],
  max_calls: 3,
  max_spend_in_cents: 500,
  calling_window_start_local_time: "09:00:00",
  calling_window_end_local_time: "18:00:00",
  milestones: [
    {name: "first_call_placed", description: "The first confirmation call was placed."},
    {name: "patient_reached", description: "A person answered and spoke with the agent."}
  ]
}' > workflow-agent.json

curl --fail-with-body --silent --show-error \
  "$RESIA_API_BASE/v1/workflow-agents" \
  --header "Authorization: Bearer $RESIA_API_KEY" \
  --header 'Content-Type: application/json' \
  --data-binary @workflow-agent.json \
  --output workflow-agent-response.json

jq '{id, review_status, is_active}' workflow-agent-response.json

Expected result: HTTP 201 with an id. Continue when review_status is approved.

The limits protect you: a run of this agent can place at most 3 calls and spend at most $5.00, and only between 9 AM and 6 PM in the patient's time zone.

Start a run

WORKFLOW_AGENT_ID=$(jq -er '.id' workflow-agent-response.json)

jq -n --arg agent "$WORKFLOW_AGENT_ID" --arg key "$(uuidgen)" '{
  workflow_agent_id: $agent,
  idempotency_key: $key,
  inputs: {
    patient_name: "Ada Lovelace",
    appointment_time: "Thursday at 3:30 PM",
    phone_number: "+12125550142",
    timezone: "America/New_York"
  }
}' > workflow-run.json

curl --fail-with-body --silent --show-error \
  "$RESIA_API_BASE/v1/workflow-runs" \
  --header "Authorization: Bearer $RESIA_API_KEY" \
  --header 'Content-Type: application/json' \
  --data-binary @workflow-run.json \
  --output workflow-run-response.json

jq '.' workflow-run-response.json

Expected result: HTTP 201 for a new run.

The idempotency_key goes in the body for workflow runs. If you send the same key with the same inputs again, Resia answers 200 with the existing run. The same key with different inputs gets 409.

inputs.timezone sets the zone for the calling window. Without it, Resia uses America/New_York.

Follow the run

WORKFLOW_RUN_ID=$(jq -er '.workflow_run_id' workflow-run-response.json)

curl --fail-with-body --silent --show-error \
  "$RESIA_API_BASE/v1/workflow-runs/$WORKFLOW_RUN_ID" \
  --header "Authorization: Bearer $RESIA_API_KEY" \
  | jq '{status, waiting_for, milestone, analysis, error_code, charges}'

The status moves through queued, running, and waiting, and ends as succeeded, failed, or cancelled. While the run waits, waiting_for says why. When it succeeds, analysis has the outcome.

Instead of polling, set run_ended_webhook_url on the Workflow Agent, or on one run, to receive a workflow_run.ended event. See Webhooks.

Cancel a run

curl --fail-with-body --silent --show-error \
  --request POST "$RESIA_API_BASE/v1/workflow-runs/$WORKFLOW_RUN_ID/cancel" \
  --header "Authorization: Bearer $RESIA_API_KEY"

Cancel is a request, not an instant stop. A run in the middle of a step finishes that step first, so the response can still say running. Read the run again to see cancelled. Resia refuses to cancel a run that already finished, with 409.

If something fails

  • 402: your prepaid balance is $0.00 or less. See Billing.
  • 422 when you start a run: the inputs do not match input_schema, or timezone is not a valid IANA name.
  • A run that failed: read error_code.
  • A run that ends without the calls you expected: check max_calls, max_spend_in_cents, and the calling window.

API reference: Workflow Agents ยท Workflow Runs