Interactions
An interaction defines a task you ask a model to perform. It combines a set of parametrized prompts, an optional schema for the response, and a model configuration. Interactions are the unit you call from your own application — through the REST API or the SDK — and the unit you version and publish.
Anatomy of an interaction
- Name
Prompts- Description
One or more prompt templates, each with a role, rendered and assembled into the message sent to the model. Prompts can be reused across interactions.
- Name
Input schema- Description
The data the interaction needs in order to render its prompts. It is derived from the parameters the prompt templates declare.
- Name
Result schema- Description
An optional JSON Schema describing the structured response you want back. The executor validates the model's output against it.
- Name
Configuration- Description
The environment and model to run on, plus execution parameters such as temperature. An interaction may set defaults and callers may override them.
Prompts and roles
A prompt template is a message with placeholders, plus a schema describing the parameters needed to render it. The simplest prompt is static and takes no parameters.
Templates use Handlebars ({{variable}}, content_type: "handlebars" — recommended) or JS Templates (${variable}, content_type: "jst") for advanced composition. See Prompts for the syntax.
Each prompt has a role:
| Role | Purpose |
|---|---|
safety | Highest priority, always rendered first. Constrains the model away from unsafe output. |
system | Sets context and persona for the task. |
user | The user's input. |
assistant | A prior model response, when you are seeding a conversation. |
tool | Carries the result of a tool call. Produced by agent runs rather than authored by hand. |
negative | What the output should avoid. Supported by some image models. |
mask | Masking input for image editing models. |
A direct call or an agent?
This is the first design decision, and it belongs before you write any prompts. It is set by is_agent in the interaction's agent_runner_options.
A direct call (is_agent: false, or omitted) is a single model call: render the prompts with the input, get the structured output back. Fast, inexpensive, and predictable in latency. The model cannot call tools or iterate.
An agent (is_agent: true) runs as a durable workflow with a tool-use loop: the model can call a tool, read the result, reason about it, call another, and eventually produce its answer.
Choose a direct call when the input already contains everything the model needs — classify, extract, summarize, translate, rewrite, score.
Choose an agent when:
- it must gather information — resolve document IDs it does not know in advance, search content, call an external API, or run code;
- steps depend on each other;
- the reasoning benefits from more than one pass, such as plan, draft, self-review, revise;
- a person needs to steer the run while it is in flight;
- the work should fan out into parallel sub-agents.
Start with a direct call and promote to an agent when the task clearly needs it. "It might occasionally need to search" is not a reason — that is just a better prompt. "It must resolve three documents from a query, then compare them" is.
Cost matters here. A direct call is one model call with predictable token usage. An agent is several model calls plus tool calls and workflow overhead — often 10 to 50 times the cost of the equivalent direct call.
See Agents for configuring an agent once you have chosen one.
Passing documents and media
There are two ways an interaction consumes documents, with different input contracts. Which you use follows from the decision above.
Direct calls: reference stored documents
Declare the input field with an editor of document or media, then pass the value as a store:<id> URI. The executor resolves it before the single model call.
// input_schema
{
"type": "object",
"properties": {
"contract": { "type": "string", "editor": "document" },
"screenshot": { "type": "string", "editor": "media" }
},
"required": ["contract"]
}
// input data
{
"contract": "store:68f5c9a0…",
"screenshot": "store:68f5d100…"
}
The two editors behave differently:
- Name
editor: "document"- Description
The server fetches the document and expands the whole content object into a template variable of the same name. Your prompt can reference any of its fields —
{{contract.text}}for the extracted text,{{contract.name}}for its display name,{{contract.properties.<key>}}for typed properties from its content type,{{contract.transcript}}for audio and video. Use this for documents the prompt needs to read inline.
- Name
editor: "media"- Description
The server fetches the file and attaches it to the message as a multimodal input. It is not expanded into the template, so do not reference it in the prompt text — the model receives it as a native attachment. Use this for images and audio.
A content object has no title field. Use {{doc.name}}.
Pass a store: reference rather than raw text or base64 whenever the document is already stored. The reference gives the executor the name, type, and metadata it needs to select the right rendition.
Agents: let the agent fetch
When the interaction runs as an agent, you usually want it to decide what to read. Grant it the document skills — learn_document_management and learn_document_search — and it can resolve IDs and search content mid-run.
A useful middle ground is to prebind the primary document with store: and let the agent fetch related ones itself.
Reusable interactions
Two flags let other agents build on an interaction you have written:
- Name
is_tool- Description
Exposes the interaction as a callable tool. Another agent can invoke it like any built-in tool, passing input that matches its input schema and receiving its result.
- Name
is_skill- Description
Exposes the interaction as a skill. Loading it injects its instructions into the calling agent and can unlock a set of tools, so one entry delivers both guidance and capability.
Both are published the same way as any other interaction, and callers should target a published version rather than the draft.
Creating an interaction
Defining an interaction's expected result
Start from what you want back, described functionally.
Summarizing an input text
A simple interaction that summarizes whatever text it is given.
Summarizing a stored document
The same task against a document already in the content store, which is a convenient way to implement retrieval-augmented generation.
Generating an interaction from a sentence
Rather than configuring one from scratch, describe what you want and refine what comes back.
Commenting a result schema
Comments on result-schema fields serve two purposes: documenting the field, and telling the model precisely what you expect in it.
Testing an interaction
Run a draft from the Playground tab on the interaction page to check its output shape and quality.
Then test it on more than one model. Different models expose different prompt weaknesses — a prompt that holds up on one provider can fall apart on another. Unless you have committed to a specific model:
- Check which environments and models the project actually has. Do not assume model IDs; they vary by project and deployment.
- Run the same input against two or three models spanning different providers.
- Read each output in full against concrete criteria: does it match the result schema, is it factually correct, is the tone and detail right, and where does the weakest model fail?
- Tighten the prompt to fix whatever the weakest model exposed, then re-run.
- Publish once every candidate produces acceptable output.
Stop when all candidates meet your quality bar, or when three attempts at the same weakness have not improved it — at that point the fix is usually structural, such as splitting the work into several interactions or giving the interaction tools.
When you change a prompt, edit the interaction in place. Do not create a second interaction to hold the new text.
Executing interactions
The point of an interaction is to call it from your own application. Invoke the REST API with the interaction ID, an input object, and optionally a configuration override. From JavaScript or TypeScript, use the Vertesia SDK.
Runs
Each execution creates a Run recording its progress and, once finished, its result or error. Runs are retained, so you can review a past execution or reuse its output.
Tag an execution with one or more tags to make its runs easy to find later.
Versions
A new interaction starts as a draft at version 1. You work on the draft, testing against different models and inputs, until it is ready for production use.
Publishing freezes the current draft as a read-only copy at its version number, then increments the draft. Publishing at version 1 gives you a permanent version 1 and moves your working copy to version 2. The draft is always what you are editing; published versions are snapshots that cannot change under a caller.
Prompts referenced by the interaction are published alongside it, as read-only copies of their current state.
A published interaction can also be made public, which lets other organizations fork it as the starting point for their own version.
