---
title: Record a run's input, result, and metadata
description: Declare input, result, and metadata schemas on a schema version,
  then record each payload on an agent instance through the HTTP API.
editUrl: true
head: []
template: doc
sidebar:
  hidden: false
  attrs: {}
pagefind: true
draft: false
---

A run usually starts with a question — which ticket to triage, which document to summarise — and ends with an answer. By default Prefactor only sees the spans in between. Recording the input and the result on the [instance](/platform/concepts/instance) itself puts both on the run's [Details tab](/admin-ui/agent-instance/details), next to metadata you choose, such as what triggered the run. By the end of this page, you have registered a run with an input and metadata, finished it with a result, and seen all three on the Details tab.

The input, result, and metadata each have their own schema, declared on the run's [activity schema](/platform/concepts/activity-schema) version. Unlike span payloads, which Prefactor records even when they diverge from the schema, an instance payload that does not match its schema is rejected. The TypeScript and Python SDKs don't send these fields yet, so this page calls the [HTTP API](/api/http) directly. The Prefactor CLI can send them too; see [From the CLI](#from-the-cli).

## Before you start

- An [API token](/platform/concepts/api-token) for the account. Create one from the [Account › API tokens tab](/admin-ui/account/api-tokens).
- The ID of the agent and of the [environment](/platform/concepts/environment) the run belongs to. Find the agent ID on the [Agents page](/admin-ui/agents) and the environment ID on the [Account › Environments tab](/admin-ui/account/environments).
- `curl`, and a shell where `PREFACTOR_API_TOKEN` holds your token.

## Steps

1. Save the registration request as `register.json`. The three schemas sit on the schema version, and the input and metadata sit beside it:

   ```json
   {
     "agent_id": "YOUR_AGENT_ID",
     "environment_id": "YOUR_ENVIRONMENT_ID",
     "agent_version": { "external_identifier": "triage-1.0.0" },
     "agent_schema_version": {
       "external_identifier": "triage-schema-1",
       "instance_params_payload_schema": {
         "title": "Ticket to triage",
         "description": "What the agent was asked to do.",
         "schema": {
           "type": "object",
           "required": ["ticket_id"],
           "properties": {
             "ticket_id": { "type": "string", "title": "Ticket ID" },
             "customer_email": { "type": "string", "title": "Customer email" },
             "priority": {
               "type": "string",
               "title": "Priority",
               "enum": ["low", "normal", "urgent"]
             }
           }
         }
       },
       "instance_result_payload_schema": {
         "title": "Triage outcome",
         "description": "What the agent decided.",
         "schema": {
           "type": "object",
           "required": ["category"],
           "properties": {
             "category": {
               "type": "string",
               "title": "Category",
               "enum": ["billing", "bug", "how_to"]
             },
             "summary": {
               "type": "string",
               "title": "Summary",
               "prefactor:format": "markdown"
             }
           }
         }
       },
       "instance_metadata_schema": {
         "title": "Run context",
         "template": "Triggered by {{trigger}}",
         "schema": {
           "type": "object",
           "required": ["trigger"],
           "properties": {
             "trigger": { "type": "string", "title": "Triggered by" }
           }
         }
       }
     },
     "params_payload": {
       "ticket_id": "T-1042",
       "customer_email": {
         "$sensitive": "string",
         "labels": ["contact_information"],
         "value": "ada@example.com"
       },
       "priority": "urgent"
     },
     "metadata": { "trigger": "support-inbox" }
   }
   ```

   Each schema entry has a `schema`, which is a JSON Schema for the payload, plus an optional `title`, `description`, and `template` beside it. Set a `title`: it becomes the section heading on the Details tab, and without one the heading falls back to "Input parameters", "Recorded result", or "Metadata". `template` is a [summary template](/api/summary-templates), and on the metadata schema it renders the summary line in the instance's heading.

   Prefactor creates the schema version if it hasn't seen this one for the agent, and reuses it otherwise.

2. Register the instance:

   ```bash
   curl -s https://app.prefactorai.com/api/v1/agent_instance/register \
     -H "Authorization: Bearer $PREFACTOR_API_TOKEN" \
     -H "Content-Type: application/json" \
     -d @register.json
   ```

   The response's `details.id` is the new instance's ID. Keep it for the next two steps.

3. Start the instance:

   ```bash
   curl -s -X POST https://app.prefactorai.com/api/v1/agent_instance/YOUR_INSTANCE_ID/start \
     -H "Authorization: Bearer $PREFACTOR_API_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{}'
   ```

4. Finish it with a result:

   ```bash
   curl -s -X POST https://app.prefactorai.com/api/v1/agent_instance/YOUR_INSTANCE_ID/finish \
     -H "Authorization: Bearer $PREFACTOR_API_TOKEN" \
     -H "Content-Type: application/json" \
     -d '{
       "status": "complete",
       "result_payload": {
         "category": "billing",
         "summary": "Customer was **charged twice**. Refund issued."
       }
     }'
   ```

## From the CLI

The same three calls with the [Prefactor CLI](/cli). Each schema and payload option takes JSON or `@path`; save the three schema entries from `register.json` as their own files first.

```bash
prefactor agent_instances register --agent_id YOUR_AGENT_ID --environment_id YOUR_ENVIRONMENT_ID \
  --agent_version_external_identifier triage-1.0.0 --agent_version_name triage-1.0.0 \
  --agent_schema_version_external_identifier triage-schema-1 \
  --instance_params_payload_schema @./input-schema.json \
  --instance_result_payload_schema @./result-schema.json \
  --instance_metadata_schema @./metadata-schema.json \
  --params_payload '{"ticket_id":"T-1042","priority":"urgent"}' \
  --metadata '{"trigger":"support-inbox"}'
prefactor agent_instances start YOUR_INSTANCE_ID
prefactor agent_instances finish YOUR_INSTANCE_ID --status complete \
  --result_payload '{"category":"billing","summary":"Customer was **charged twice**. Refund issued."}'
```

To discard an instance's stored sensitive values, run [`prefactor agent_instances discard_sensitive YOUR_INSTANCE_ID`](/cli).

## Verify

Open the instance from the [Agent page › History tab](/admin-ui/agent/instances) and select its Details tab. Below the lifecycle fields you should see three sections, titled **Ticket to triage**, **Triage outcome**, and **Run context**. Each lists its fields in alphabetical order by key, labelled with the schema's `title`. The heading above the tabs shows "Triggered by support-inbox".

The customer email reads as a labelled placeholder rather than a value. Select **Show sensitive information for this instance** in the heading to reveal it; the value is hidden again the next time you open the page.

## What each payload accepts

| Field | Set when | Rule |
| --- | --- | --- |
| `params_payload` | You register the instance. | Checked against `instance_params_payload_schema`. Omitting it is checked as `null`, so it can be left out only when that schema allows `null`. |
| `metadata` | You register the instance. It can't change afterwards. | Checked against `instance_metadata_schema`. Omitting it is checked as an empty object. |
| `result_payload` | You finish the instance with status `complete` or `failed`. | Checked against `instance_result_payload_schema` when you finish with `complete`, even if omitted. Optional on `failed`, but checked when sent. Ignored on `cancelled`. |

A payload needs a schema. Sending `params_payload`, `metadata`, or `result_payload` for a schema version that doesn't declare the matching schema is an error.

Prefactor checks the value inside a `$sensitive` marker against the schema, not the marker around it.

## Mark sensitive values

Instance payloads always parse [sensitive encoding](/api/sensitive-encoding); there is no flag to turn on. Wrap a value in a marker, as `customer_email` is above, and Prefactor stores it separately and redacts it by default. A literal `$sensitive` key in your own data needs the escape wrapper described in [Sensitive encoding](/api/sensitive-encoding#escaping-literal-sensitive-keys).

To delete the stored values for good, call [the instance's discard-sensitive operation](/api/platform/operations/actionagentinstancediscardsensitive). It redacts the input, result, and metadata, and leaves the spans alone.

## Control how a field appears

The Details tab reads display hints from each property of your schema:

- `title` and `description` replace the key as the field's label and add a line beneath it. A field without a `title` shows its key in a monospace font.
- A string with `"format": "date-time"` or `"format": "date"` is shown in the viewer's timezone or as a plain date.
- A string with `"prefactor:format": "markdown"` is rendered as formatted text.
- A string with `"prefactor:format": "verdict"` shows a pass or fail badge when its value is `pass` or `fail`.
- Objects and arrays appear as formatted JSON.

## If it didn't work

- **`params_payload` or `metadata` "is not allowed".** The schema version has no schema for it. Add `instance_params_payload_schema` or `instance_metadata_schema` to `agent_schema_version`.
- **`metadata` "is required".** The metadata schema has required fields, so the request must include `metadata`.
- **A validation error naming `params_payload` or `metadata`.** The payload doesn't match its schema. The message says which property failed.
- **Finish returns an error with code `unexpected`.** The request sent `result_payload` for a schema version with no result schema. Add `instance_result_payload_schema` to the schema version, or leave `result_payload` out.
- **The Details tab shows "No payloads for this instance."** The instance has no recorded input, result, or metadata. Check that you sent them on the right call.

## Related

- [Instance](/platform/concepts/instance#input-result-and-metadata) — what the three payloads are and how they differ from spans.
- [Activity schema](/platform/concepts/activity-schema) — the schema version these schemas live on.
- [Sensitive encoding](/api/sensitive-encoding) — the marker format.
- [Summary templates](/api/summary-templates) — the language behind `template`.
- [Agent › Instance › Details tab](/admin-ui/agent-instance/details) — where the payloads appear.