Skip to content

Schemas and result schemas

Prefactor agent schemas describe the expected shape of span payloads and span results for each span type. In the SDK this is agentSchema / the agent schema object; in the platform it is the activity schema. You provide these through httpConfig.agentSchema and they are registered with the agent manager during initialisation. Every span type must have payload and result definitions in the activity schema; integration packages supply permissive defaults for their prefixed span types so you can start recording traces before you write tight, custom schemas.

Schemas describe rather than enforce. The web app reports whether incoming payloads match the schema, and that shape is what lets you organise and understand the recorded data. The SDK records spans regardless of whether they match the schema.

Each default schema defines both span_schemas and span_result_schemas. This separation lets you validate request-side fields and result-side fields independently, which is useful when your workflows evolve at different speeds for inputs and outputs. Out of the box, the SDK defaults are permissive: they describe a generic object and allow properties you have not listed yet, so they do not block incremental instrumentation.

When you need stronger constraints, provide your own schema object in httpConfig.agentSchema. A common pattern is permissive definitions for chat turns (user_message, assistant_message) alongside tighter definitions for each tool span type so payloads and results match that tool’s real contract.

The agent schema can also carry one or more named quality schemas, each declaring the shape of an evaluation payload you attach to a run after it finishes. See Quality evaluations.

An agentSchema for a conversational agent: open shapes for messages, and per-tool definitions for web_search and read_file. This example uses init from @prefactor/core with a provider so you can pass agentSchema on the client config. For the usual middleware-only path, see Getting started with the TypeScript SDK.

import { init } from '@prefactor/core';
import { PrefactorLangChain } from '@prefactor/langchain';
const openObject = {
type: 'object',
additionalProperties: true,
} as const;
const agentSchema = {
span_schemas: {
user_message: openObject,
assistant_message: openObject,
web_search: {
type: 'object',
properties: {
query: { type: 'string' },
max_results: { type: 'number' },
},
required: ['query'],
additionalProperties: false,
},
read_file: {
type: 'object',
properties: {
path: { type: 'string' },
},
required: ['path'],
additionalProperties: false,
},
},
span_result_schemas: {
user_message: openObject,
assistant_message: {
type: 'object',
properties: {
content: { type: 'string' },
},
required: ['content'],
additionalProperties: true,
},
web_search: {
type: 'object',
properties: {
results: { type: 'array' },
},
required: ['results'],
additionalProperties: true,
},
read_file: {
type: 'object',
properties: {
contents: { type: 'string' },
},
required: ['contents'],
additionalProperties: false,
},
},
};
const prefactor = init({
provider: new PrefactorLangChain(),
httpConfig: {
apiUrl: process.env.PREFACTOR_API_URL!,
apiToken: process.env.PREFACTOR_API_TOKEN!,
agentIdentifier: '1.0.0',
agentSchema,
},
});

The Python SDK follows the same schema model. Pass your schema as agent_schema in the client config:

import os
from prefactor_core import PrefactorCoreClient, PrefactorCoreConfig
from prefactor_http import HttpClientConfig
OPEN_OBJECT = {"type": "object", "additionalProperties": True}
agent_schema = {
"span_schemas": {
"user_message": OPEN_OBJECT,
"assistant_message": OPEN_OBJECT,
"web_search": {
"type": "object",
"properties": {
"query": {"type": "string"},
"max_results": {"type": "number"},
},
"required": ["query"],
"additionalProperties": False,
},
"read_file": {
"type": "object",
"properties": {
"path": {"type": "string"},
},
"required": ["path"],
"additionalProperties": False,
},
},
"span_result_schemas": {
"user_message": OPEN_OBJECT,
"assistant_message": {
"type": "object",
"properties": {
"content": {"type": "string"},
},
"required": ["content"],
"additionalProperties": True,
},
"web_search": {
"type": "object",
"properties": {
"results": {"type": "array"},
},
"required": ["results"],
"additionalProperties": True,
},
"read_file": {
"type": "object",
"properties": {
"contents": {"type": "string"},
},
"required": ["contents"],
"additionalProperties": False,
},
},
}
config = PrefactorCoreConfig(
http_config=HttpClientConfig(
api_url="https://app.prefactorai.com",
api_token=os.environ["PREFACTOR_API_TOKEN"],
agent_schema=agent_schema,
)
)
client = PrefactorCoreClient(config)
await client.initialize()

See the Python SDK reference for the exact parameter names.

The schema you register from the SDK appears in the Activity schema tab of the agent in the Prefactor web app. The span type identifiers you define (for example user_message, assistant_message, web_search) correspond to the span types shown there. See the Agent › Activity schema tab to view deployed schemas and their validation status.