Run an Orchestration Agent

An Orchestration Agent runs a task with several steps, such as a call, a wait, and a retry. In this guide, you will create an Orchestration Agent that calls a person to confirm an appointment and tries again if nobody answers. Then you will start one run and read its result. Read Orchestration Agents first for the concepts.

Before you start

  • Complete Get access. Keep that terminal open, with RESIA_API_BASE and RESIA_API_KEY set.
  • An approved, active Call Agent for the confirmation call. Its input_schema must accept the values the Orchestration Agent supplies, such as patient_name and appointment_time. See Change what an agent says.
  • A run places real calls. Normal call charges apply.

Create the Orchestration 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."}
  ]
}' > orchestration-agent.json

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

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

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

A run of this agent can place at most 3 calls and spend at most $5.00. It can call only between 9 AM and 6 PM in the patient's time zone.

Start a run

ORCHESTRATION_AGENT_ID=$(jq -er '.id' orchestration-agent-response.json)

jq -n --arg agent "$ORCHESTRATION_AGENT_ID" --arg key "$(uuidgen)" '{
  orchestration_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"
  }
}' > orchestration-run.json

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

jq '.' orchestration-run-response.json

Expected result: HTTP 201 for a new run.

The idempotency_key goes in the body for orchestration 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

ORCHESTRATION_RUN_ID=$(jq -er '.orchestration_run_id' orchestration-run-response.json)

curl --fail-with-body --silent --show-error \
  "$RESIA_API_BASE/v1/orchestration-runs/$ORCHESTRATION_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. It ends as succeeded, failed, or cancelled. While the run waits, waiting_for says why. When it succeeds, analysis has the outcome.

You can receive an orchestration_run.ended event when the run ends. Set run_ended_webhook_url on the Orchestration Agent or on one run. See Webhooks.

To list runs, use GET /v1/orchestration-runs, filtered by orchestration_agent_id or by a tag pair. See List runs.

To list the calls or the chats that this run started, send orchestration_run_id to GET /v1/calls or GET /v1/chats. To see each step of the run, add include_tool_activity=true to the read. Do this when you open the run or after its status changes, not on every status check.

See runs in the portal

Open History → Runs to see all runs. The Runs tab on an Orchestration Agent shows that agent's runs. Select a run to see these details:

  • Its status and the reason for a wait or failure.
  • Its milestone and analysis.
  • Its charges for calls, messages, and model tokens.
  • Its Timeline: the run's calls, chats, milestones, and steps, in time order. A run that started before Resia recorded step times shows no step times.

An open run refreshes until it ends. Select Cancel run to cancel a run before it ends.

Cancel a run

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

Cancel is a request, not an instant stop. A run finishes its current step first. 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.

Next steps

API reference: Orchestration Agents · Orchestration Runs