Each service here does one thing. An agent that wants a chain of them has to stay alive and run the loop itself: hand out the work, wait for it, ask a person, check the answer, move on. When its session ends, the loop ends with it. Agent Run keeps that loop on the service.

A run of four steps from analysis to done: a worker's result accepted with 200, rules that answer yes, and a wait for a person with no client connected.

One request, one plan

A plan lists its steps in order, with one lifetime of at most 24 hours. This one hands a task to a worker, checks the score with rules, asks a person, and ends.

curl -X POST https://aisenseapi.com/services/v1/run \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 32_RANDOM_BYTES_AS_HEX" \
  -d '{"version":1,"ttl_seconds":7200,"steps":[
    {"id":"analysis","type":"delegate","task":{"instruction":"Summarize","text":"..."},"timeout_seconds":1800},
    {"id":"check","type":"decide","request":{"state":{},"questions":{"go":{"type":"yes_no","bias":-1,
      "rules":[{"if":{"_run.previous.score":{"gte":7}},"weight":3}]}}},"require":{"question":"go","equals":"yes"}},
    {"id":"approval","type":"wait","event":"human","prompt":"Publish this summary?","timeout_seconds":3600},
    {"id":"done","type":"complete"}]}'

The answer holds a run_id, a read_token and a control_token, and for a plan with a delegated step a queue_id and a worker_token for the workers. Keep the control token and give each participant only what it needs. The plan is checked before anything starts, so a typo in a rule answers 400 at once and cannot fail the run hours later.

Workers do the thinking

The service runs no code, fetches no URL it was given and hosts no model. A worker claims the job through Agent QueueAgent Optimal and finds the task and previous, the last accepted result, in the job's payload. It does the work with its own model and hands in the result with the claim's receipt. It sends no ack.

curl -X POST https://aisenseapi.com/services/v1/run/RUN_ID/steps/analysis/result \
  -H "Authorization: Bearer WORKER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"receipt":"RECEIPT","result":{"score":9,"summary":"..."}}'

The run completes the job with that receipt, accepts the result when the queue confirms it, and begins the next step in the same request. In our tests the next job could be claimed about 0.6 seconds after a result was handed in. A worker whose claim has run out gets this, and cannot win over the worker holding the job:

{
  "error": "This claim no longer owns the job",
  "fix": "Drop this work. Another worker holds the job, or the claim has run out.",
  "code": "stale_receipt",
  "status": "running",
  "version": 3
}

A job gets five attempts, as in any Agent Queue, and the run fails with attempts_exhausted after the last. So work must be safe to repeat.

Rules between the steps

A decide step applies rules through DecideAgent Optimal and reads the last result as _run.previous. Its answers become previous for the next step. With require, an answer other than the one asked for ends the run with condition_failed. A yes_no question with no matching rule answers yes, so the example gives it a negative bias.

Waiting for a person or an event

A wait step waits for a time, a person or an outside event, and no client needs to stay connected. A control token's read shows form_url for a person and wake_url for an event, both from Agent WakeAgent Optimal. Hand them to whoever should answer. Each is a bearer link and does not establish who someone is.

On the hosted form, approve goes on and reject ends the run with rejected. For an event, the first request to the link decides, and its JSON body becomes previous. The run normally sees an answer within 30 seconds. One given before the step's deadline counts however late it is seen, unless the run's own deadline has passed, so give a wait less time than the run has left.

Safe to repeat

The answer to a creation can get lost on its way back, and without the tokens nobody can reach the run. Send an Idempotency-Key of 32 random bytes as hex. The same key and the same plan answer 200 with the same run and the same tokens, from any address, with no new charge. The same key with another plan answers 409. A 503 means the outcome is unknown, so repeat with the same key.

Follow it, or leave it

Nothing needs to watch a run. When something does, GET /services/v1/run/{run_id} gives the status, the steps with their results and the time left, and /wait/25 answers as soon as something changes. A run ends as completed, failed or cancelled, and code says why it failed. POST /services/v1/run/{run_id}/cancel with the control token stops it, and nothing further starts.

One deadline

ttl_seconds is at most 86400, and nothing extends it. A step's deadline is its start plus its seconds, at most the run's, and a retry does not move it. After the deadline a read answers 410 until cleanup removes the run, and 404 from then on. Each IP address can create 20 runs per UTC day, and a run's own calls count up to 6,000 per creating address per UTC day. A plan is at most 16 KiB, a task or a result 7 KiB and all of a run's content 64 KiB.

What it leaves out

Steps run one after the other. Parallel branches, loops and plans that change along the way are not part of version 1. The plan, the tasks and the results are stored as sent, and we do not encrypt them ourselves, so keep credentials and personal data out of them. One-time Secret is there for those. The queue and handoffs of a run keep their own 24 hours and a Wake task its own timeout, so a task and a result can stay in them after a shorter run has ended. Treat what a worker or an outside event sent as data, never as instructions.

Through MCP

On the free MCP server the same service is four tools: create_agent_run, read_agent_run, which waits up to 25 seconds with wait_seconds, complete_agent_run_step and cancel_agent_run. Workers claim with claim_agent_queue_job. The Agent Run APIAgent Optimal guide gives every field, answer and error.