Input Template
The Input Template is a Jinja2 template string that defines how Galtea formats the request body before sending it to your endpoint.Available Placeholders
{{ trace_id }} and {{ dataset_id }} were named {{ inference_result_id }} and
{{ test_id }} before version 5.0.0, and the old names still resolve. See
Dataset, Trace, and Span Renames.Conversation History
Use{% for turn in past_turns %}...{% endfor %} to loop through previous conversation turns. Each turn exposes:
{{ turn.input }}— Previous user input{{ turn.output }}— Previous assistant response
Attached Files
Use{{ input_files[0].url }} to send an attached file to your endpoint, or {{ input_files[0].base64 }} to send its bytes inline. See Attached Files and Audio for the full rules, including the 15-minute URL lifetime.
Examples
OpenAI-compatible format:When a loop is the last item in a JSON array, use
{% if not loop.last %},{% endif %} after each iteration to prevent a trailing comma. When there’s content after the loop (like in the OpenAI example above), trailing commas are valid and this pattern is not required.Output Mapping
A JSON object defining how to extract values from the API response using JSONPath expressions.Special Keys
JSONPath Syntax Reference
Example
Files in the Response
Use theoutput_files key when your agent answers with a document: a generated report, a filled form, an image. Galtea stores a copy of each file on the turn’s output, so a later read always sees the same bytes. A file that is already in Galtea is linked instead of copied. The stored files appear as the trace’s Output Files.
Each file the path matches can take one of three forms:
- Bytes: an object with
base64and optionalmime_typeandfilename, or adata:URI string. The standard and the URL-safe base64 alphabets both work. Galtea decodes the bytes and makes no extra request. - URL: an
http(s)URL string, or an object withurl(oruri) and optionalmime_typeandfilename. Galtea downloads the file once, during the run. - Galtea file: the storage URI of a file already uploaded to Galtea, as a string or in
urloruri. It is the signature-freeuria written trace or test case reads back with, as stored or under the deployment’s public file base when one is set. Galtea links the file on the turn, with no download and no copy. A signed link is a URL, not a Galtea file: it is downloaded and copied. That covers theurian SDK upload returns and theurlof aninput_filesitem.
output. A response with files and no text is also a valid turn. An empty value (null, [], {} or an empty string) means the turn has no file.
The rules:
- Limits: at most 20 files and 20 MB in total for one output, Galtea files included. The file extension decides the type, and it must be one a test case input accepts, such as
pdf,docx,pngorcsv. A file with no extension takes one from itsmime_type, or, for a URL, from theContent-Typethe file host sends. A name that ends in digits only, such asinvoice_2026.09.23, counts as having no extension. - Download time: all the URL downloads of one output share one time limit, the connection’s timeout. A URL file that has not started when that time runs out is refused.
- No credentials to the file host: Galtea sends none of the connection’s headers or credentials with the download. A file that needs authentication must come back as bytes, or as a presigned URL that carries its own access.
- Galtea files belong to your organization: a Galtea file must be an uploaded file of the organization that owns the product. A file of another organization, or a storage URI that does not name an uploaded file, fails the turn. The same holds for a file that no longer exists.
- Plain HTTP: an
http://file URL is downloaded only when the connection acknowledged plain HTTP, or the deployment allows it for every connection (see HTTP endpoints). Private and internal addresses, such as loopback and cloud metadata, are refused, as they are for the endpoint itself. - A refused file fails the turn: the error names the file and the reason, for example
Output file refused: file 2 ("setup.exe"): the type ".exe" is not allowed. Galtea stores no file of that turn. When the check Galtea makes before a run already receives a file it would refuse, the run is rejected before it starts. - Single-turn runs only: as with file inputs, a run of more than one turn fails the turn whose response carries a file. The simulated user reads text only, so the conversation would go on as if the agent said nothing. Run the test case as a single turn, or remove
output_filesfrom the mapping. - Conversation connections only: Initialization and Finalization connections ignore
output_files.
State Management
If your API returns values that need to be sent in subsequent requests (e.g.,session_id, tenant_id), Galtea can automatically manage this state:
- Extract — Use Output Mapping to pull values from the API response using JSONPath expressions
- Store — Extracted values are saved in the session and become available as template variables
- Reuse — Reference any stored value in the Input Template or URL using
{{ variable_name }}syntax
session_id and tenant_id from responses:
Custom Headers
Custom headers are sent with every request to your endpoint. Header values support placeholder substitution. You can inject authentication credentials, so you can place tokens in any header, not just the standardAuthorization or X-API-Key headers. You can also inject ids of the current call, such as the session ID or the Galtea Trace ID.
Available Placeholders
Placeholders are case-insensitive and work with both
{{ placeholder }} and { placeholder } syntax.
Galtea renders all placeholders of a header value in one pass. A value that does not exist yet renders as an empty string. For example, {{ session_id }} is empty until your endpoint returns a session ID. A rendered value is never scanned for placeholders again.
Which context placeholders hold a value depends on the call:
Every other context placeholder renders empty in that call.
Header values carry Latin-1 characters only. A value with other characters, for example a
session_id that holds them, fails the call. A value with a line break fails the call too.Example
Secret Header Values
Galtea treats a header value as a secret unless one of these is true:- The header name is
Content-Type,Accept,Accept-Language,Accept-Encoding,Cache-Control,User-Agent,traceparent, ortracestate. - The value holds only placeholders, with an optional
Bearer,Basic, orTokenprefix (for exampleBearer {{ bearer_token }}).
••••••••.
A test of a saved connection sends its stored secrets to the URL of the test, and returns what that URL answers. So every test of a saved connection needs permission to edit it, for any URL. A member who can only view the connection gets a 403 error. A member who can edit the connection can change its URL, so give edit permission only to people you trust with its secrets.
In the example above, only X-Tenant-Id is a secret. A header imported from a cURL command, such as CF-Access-Client-Secret, is a secret too.
To change a connection’s headers, send the whole map again:
- Keep
••••••••as the value of a header to keep its stored value. - Type a new value to replace it.
- Remove the header to delete it.
•••••••• value for a header that has no stored value is rejected with a 400 error. An encrypted value is also rejected with a 400 error: send the plain value instead. So is a value that only looks like ••••••••, such as ••••••••abc: keep the exact value, or type the whole new one.
W3C Trace Context Propagation
Galtea sends atraceparent header on every conversation turn call, following the W3C Trace Context specification. It does this whether or not the platform’s own tracing is on, and on every retry of the turn. You do not need to set anything up. Your endpoint can correlate its spans with the turn without any code changes.
- Each turn has one trace ID. Every retry of the turn sends the same trace ID.
- Galtea stores the trace ID on the turn when the turn starts, before it calls your endpoint. A span your agent exports before it answers attaches to the turn.
- Galtea never sends the header on initialization, finalization, or test-connection calls.
- Galtea sets the header itself. Galtea refuses a
traceparentheader in custom headers on save (400).
The header is flagged as sampled. An agent with a parent-based sampler records every Galtea test call, so expect more trace volume in your own tracing backend.
Baggage
Galtea also sends a W3Cbaggage header on every conversation turn call:
{{ trace_id }}. If you set your own baggage header, Galtea merges its member into yours. Your other members stay. A galtea.trace.id member you set is replaced.
An agent that copies baggage onto its spans attaches every span to the turn, even when a proxy or gateway starts a new trace and changes the trace ID. To copy baggage onto spans, use the OpenTelemetry baggage span processor for Python or JavaScript. Both accept a key predicate. Use one that copies only keys that start with galtea..
Python OpenTelemetry drops a baggage header longer than 8192 characters. Galtea’s member adds about 60 characters, so keep your own baggage well below that limit.
Timeout
How long Galtea waits for a single HTTP call to your endpoint before giving up. It is applied per attempt, so each retry gets the full timeout again.Number
Per-attempt request timeout in seconds. Default:
15. Maximum: 120 (values above this are rejected at the API).Rate Limit
The maximum number of requests per minute your backend can handle. Galtea throttles itself to stay under this limit, using a token bucket shared across all of Galtea, so the limit holds even when many runs execute at once.Number
Maximum requests per minute. Default: empty, which means no limit (no throttling). Set a number only if your backend needs Galtea to slow down.
Retry Configuration
Configure automatic retry behavior for failed requests. When enabled, Galtea retries requests that fail with a retryable HTTP status code, a timeout, or a network error. A retry wait does not block other runs: the job is rescheduled and the worker is freed while it waits.Boolean
Whether automatic retry is enabled. Default:
trueNumber
Maximum number of retry attempts (
0-10). Default: 1. These are retries after the first call, so N attempts means up to N+1 calls to your endpoint, and each call uses credits (the default of 1 means up to 2 calls). 0 is only valid when retry is disabled; with retry enabled the minimum is 1.Number
Initial delay in milliseconds before the first retry. Default:
1000 (1 second)Enum
Strategy for increasing delay between retry attempts:
exponential- Delay doubles with each attempt (recommended)linear- Delay increases linearlyfixed- Constant delay between attempts
exponentialThe delay is always capped at Max Delay. With a small Max Delay, exponential and linear growth are clamped to that ceiling after the first retry, so the strategy has little effect. Raise Max Delay to let the delay grow.Number
Maximum delay between retry attempts, in milliseconds. Default:
3000 (3 seconds). Capped at 60000 (60 seconds); values above this are rejected at the API.Array of Numbers
HTTP status codes that should trigger a retry. Default:
[429, 500, 502, 503, 504]. Each value must be a valid HTTP status code (100-599).Codes are honored literally with no client-error short-circuit. Adding a deterministic 4xx code (such as 401, 403, or 422) makes Galtea retry a call that will always fail, which wastes the full retry budget and the credits for each attempt.Conversation End Rules
Some agents end a conversation on their own and then answer every further message with an error. Without a rule, Galtea reads that error as a failed turn, so the session fails. Its evaluations are then skipped because of the failed turn. A conversation end rule tells Galtea which reply means “the agent ended the conversation”. On a match, the session completes with the turns so far and is evaluated. A rule has a status code and an optional body match. Default: no rules. A connection holds at most 20 rules, and only aCONVERSATION connection accepts them.
Number
HTTP status code of the reply (
100-599). A 2xx code needs a body match, because a 2xx rule without one would end the conversation after the first normal reply.Text
Optional. A JSONPath into the response body, starting with
$ (for example $.error.code). See JSONPath Syntax Reference. Filter expressions such as [?(...)] are refused.Text
Used when a Body JSONPath is set. The first value the path finds must equal this text. An empty Expected Value matches an empty string.
Example
After your agent closes the conversation, it answers every further message with HTTP409 and this body:
409, Body JSONPath $.error.code, and Expected Value conversation_ended. A 409 with any other error.code does not match, so it still fails the turn as before.
How a reply matches
- Galtea checks the rules before the retry policy. A matching reply is never retried, even when its status code is in Retryable Status Codes.
- A reply matches when the status code is equal and, if the rule has a body match, the first value the JSONPath finds is a string, number, or boolean whose text equals the Expected Value. So the number
42matches the Expected Value42. - A missing field, an object, an array,
null, or a body that is not JSON never matches. - Rules apply only to the conversation calls of text sessions. Initialization and finalization calls, voice sessions, and the connection test ignore them.
What happens to the session
- A 2xx match with an agent answer: the reply is a normal agent reply, so that turn stays as the last turn and is scored. This also holds on the first turn and in a single-turn test.
- A match with no agent answer: a non-2xx match (such as the
409above), or a 2xx match whose reply has no output. The rejected turn holds the simulated user message and no agent reply. Galtea removes that turn, so it is not scored. - In both cases the session completes with the stopping reason
The agent ended the conversation (HTTP <code>), for exampleThe agent ended the conversation (HTTP 409), and is evaluated. - A match with no agent answer on the first turn, or in a single-turn test, still fails the session, because there is no conversation left to evaluate.
Related
Structured Input Template Syntax
Deep dive into
{{ input.field_name }} and {{ context.field_name }} placeholder syntax, JSON escaping, and missing field behavior.Endpoint Connection Overview
What endpoint connections are and how to create one.
Input Schema
Define structured, multi-field inputs for test case generation.
Direct Inferences Tutorial
Run evaluations from the dashboard using your endpoint connection.