Create a custom operator
The platform operator catalogue covers common analysis, but you can define your own for anything specific to your business. A custom operator is the same shape as a platform one — a prompt paired with a typed output — and is used in configurations exactly the same way. This guide creates one, then references it in a configuration.
The examples use the base path https://api.simwood.com/intelligence/v1 and a Bearer API key — see Authentication. You'll need intelligence:write.
1. Choose an output type
Decide what shape the result should take, from the output type vocabulary. The type fixes the result shape and what you can query and gate actions on:
- a
classificationfor one value from a set, - a
booleanfor detected-or-not, - a
scorefor a numeric assessment, - a
multi_tagfor zero or more values from a set, - an
extractionfor a specific piece of information, textfor free-form generated output.
This guide builds a classification operator that grades complaint severity.
2. Write the prompt and output config
The prompt is natural-language instruction to the model describing what to look for and how to reason about it. The output_config constrains the result — for a classification, the full set of allowed values:
curl -X POST https://api.simwood.com/intelligence/v1/operators \
-H "Authorization: Bearer sk_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "complaint-severity",
"description": "Grades how serious a customer complaint is.",
"prompt": "Assess the severity of the customer'\''s complaint in this conversation. Respond with one of: low, medium, high.",
"output_type": "classification",
"output_config": { "values": ["low", "medium", "high"] },
"model_tier": "standard",
"include_reasoning": true
}'
A few rules:
nameis kebab-case, unique within your account, and must not collide with a platform operator's name.model_tierisfastfor high-frequency, latency-sensitive analysis orstandardfor quality over speed.include_reasoningasks the model to justify each result; the justification arrives in thereasoningfield.
Note the operator declares what to analyse and how — not when. Granularity is set later, on the operator reference inside a configuration.
3. Optional — parameterise it
If the same operator should run against different inputs across configurations, declare a parameter and reference it in the prompt as {{parameters.<name>}}. A kb_document parameter resolves to a knowledge base document whose text is substituted into the prompt at session start:
{
"name": "protocol-adherence",
"description": "Assesses whether the handler followed the protocol.",
"prompt": "The protocol for this call is:\n\n{{parameters.protocol-document}}\n\nAssess adherence. Respond with one of: on_track, minor_deviation, major_deviation.",
"output_type": "classification",
"output_config": { "values": ["on_track", "minor_deviation", "major_deviation"] },
"model_tier": "standard",
"parameters": [
{ "name": "protocol-document", "type": "kb_document", "description": "The protocol document to assess against." }
]
}
The parameter's value — the document id — is supplied where the operator is referenced in a configuration, so one operator serves many protocols.
4. Reference it in a configuration
A custom operator is referenced like any other — by name, with its granularity and any parameter values:
{
"name": "complaint-severity",
"granularity": { "on": "conversation_end" }
}
Add it to a configuration's operators list and it runs on every session that configuration drives. From there, the Analyse a live call flow is identical.
Versioning
Editing a custom operator creates a new version rather than changing the existing one, and configurations stay pinned to the version they reference — so an edit never silently changes running analysis. GET /operators/{name}/versions lists the history, and a configuration moves to a newer version only when you upgrade its references explicitly.