Skip to content

Record a run with the API

You don’t need an SDK to send runs to Prefactor. If your agent is written in a language we don’t have an SDK for, or you’d rather not add a dependency, you can record a run with five HTTP requests. This guide walks through them with curl, so you can follow the same steps from any language.

By the end you’ll have an instance with one span on your agent’s History tab.

  • An agent registered in Prefactor. See Register an agent.
  • A deployment token for that agent and the environment you’re recording to, in PREFACTOR_API_TOKEN. See Create a deployment token. A deployment token already knows its agent and environment, so the requests below don’t need to name them.
Terminal window
export PREFACTOR_API_TOKEN="<your deployment token>"
export PREFACTOR_URL="https://app.prefactorai.com/api/v1"
  1. Register the instance.

    Registering creates the instance and tells Prefactor which version of your agent is running and which span types it records. The agent_version and agent_schema_version are found or created by their external_identifier, so sending the same values on every run is safe.

    Terminal window
    curl -X POST "$PREFACTOR_URL/agent_instance/register" \
    -H "Authorization: Bearer $PREFACTOR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
    "idempotency_key": "register-run-0001",
    "agent_version": {
    "external_identifier": "1.0.0",
    "name": "Support agent"
    },
    "agent_schema_version": {
    "external_identifier": "support-agent-schema-1",
    "span_type_schemas": [
    {
    "name": "support:llm",
    "params_schema": { "type": "object" },
    "result_schema": { "type": "object" }
    }
    ]
    }
    }'

    The response’s details.id is the instance ID. Save it:

    Terminal window
    export INSTANCE_ID="<details.id from the response>"
  2. Start the instance.

    Terminal window
    curl -X POST "$PREFACTOR_URL/agent_instance/$INSTANCE_ID/start" \
    -H "Authorization: Bearer $PREFACTOR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "idempotency_key": "start-run-0001" }'

    The instance is now Active.

  3. Open a span for a step the agent takes.

    schema_name must match a span type you declared when you registered. The payload is what the step received.

    Terminal window
    curl -X POST "$PREFACTOR_URL/agent_spans" \
    -H "Authorization: Bearer $PREFACTOR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
    "idempotency_key": "span-run-0001-1",
    "details": {
    "agent_instance_id": "'"$INSTANCE_ID"'",
    "schema_name": "support:llm",
    "status": "active",
    "payload": { "prompt": "Where is my invoice?" }
    }
    }'

    Save the span’s details.id:

    Terminal window
    export SPAN_ID="<details.id from the response>"
  4. Finish the span with what the step returned.

    Terminal window
    curl -X POST "$PREFACTOR_URL/agent_spans/$SPAN_ID/finish" \
    -H "Authorization: Bearer $PREFACTOR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{
    "idempotency_key": "span-run-0001-1-finish",
    "status": "complete",
    "result_payload": { "text": "Your invoice is under Billing." }
    }'

    Use "status": "failed" when the step failed.

  5. Finish the instance.

    Terminal window
    curl -X POST "$PREFACTOR_URL/agent_instance/$INSTANCE_ID/finish" \
    -H "Authorization: Bearer $PREFACTOR_API_TOKEN" \
    -H "Content-Type: application/json" \
    -d '{ "idempotency_key": "finish-run-0001", "status": "complete" }'

Open the agent’s History tab. The run is at the top with the status Complete. Select View to see the support:llm span with its payload and result.

  • Idempotency keys. Send a new, unique idempotency_key with every write, such as a UUID, and reuse it only when you retry that same request. A retried request then can’t record a step twice.
  • Retries and rate limits. Retry 429 and 503 responses after the wait in the Retry-After header. See Rate limits and HTTP API.
  • Real schemas. Replace { "type": "object" } with JSON schemas for each span type, and add data risk so Prefactor can score runs. See Activity schema.
  • Termination. When someone terminates a run from the web app, Prefactor keeps accepting spans, but every span create and finish response then carries "control": {"terminate": true, "reason": "..."}. Check for it and stop the agent’s work. See Handle instance termination.
  • Fewer requests. Create a span already finished by sending "status": "complete" with result_payload, started_at and finished_at in step 3, and skip step 4. To send several writes in one request, use bulk operations.
  • 401 bad_authtoken. The token is wrong, expired, suspended or revoked. Check it on the Account › API tokens tab.
  • 400 validation_errors on a span. schema_name doesn’t match a span type in the registered schema, or the payload doesn’t match that span type’s params_schema. The errors map names the field.
  • Registering fails without a deployment token. With an account token, send agent_id and environment_id in step 1 as well.
  • API - what the API covers, and where to find the OpenAPI spec.
  • Platform API operations - every operation, with its parameters and responses.
  • SDK overview - the SDKs make these requests for you.