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 SDK terms, 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 are used for observability and governance — they describe expected structure, and any conformance gaps are visible in the web app. 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.

An agentSchema for a conversational agent: open shapes for messages, and per-tool definitions for web_search and read_file:

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.