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.
Before you start
Section titled “Before you start”- 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.
export PREFACTOR_API_TOKEN="<your deployment token>"export PREFACTOR_URL="https://app.prefactorai.com/api/v1"Record the run
Section titled “Record the run”-
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_versionandagent_schema_versionare found or created by theirexternal_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.idis the instance ID. Save it:Terminal window export INSTANCE_ID="<details.id from the response>" -
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.
-
Open a span for a step the agent takes.
schema_namemust match a span type you declared when you registered. Thepayloadis 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>" -
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. -
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" }'
Verify
Section titled “Verify”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.
Make it production-ready
Section titled “Make it production-ready”- Idempotency keys. Send a new, unique
idempotency_keywith 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
429and503responses after the wait in theRetry-Afterheader. 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"withresult_payload,started_atandfinished_atin step 3, and skip step 4. To send several writes in one request, use bulk operations.
If something goes wrong
Section titled “If something goes wrong”401 bad_authtoken. The token is wrong, expired, suspended or revoked. Check it on the Account › API tokens tab.400 validation_errorson a span.schema_namedoesn’t match a span type in the registered schema, or the payload doesn’t match that span type’sparams_schema. Theerrorsmap names the field.- Registering fails without a deployment token. With an account token, send
agent_idandenvironment_idin step 1 as well.
Related
Section titled “Related”- 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.