Skip to main content

Configuration

What shapes a generation: the model and sampling parameters, the agent profile in effect, conversation-level settings, and how history is kept within the context window.

Generation Config

Control how the AI generates responses by updating the default generation config.

curl -X POST https://api.travila.ai/api/v1/llm/update-default-generation-config \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"conversationKey": "support-chat-001",
"defaultGenerationConfig": {
"model": "anthropic/claude-sonnet-5",
"temperature": 0.7,
"maxOutputTokens": 2048,
"topP": 0.9
}
}'

The four fields above are the ones most conversations need:

FieldDescriptionDefault
modelModel to generate with — see Available ModelsPlatform default
temperatureRandomness (0.0 = deterministic, 2.0 = creative)1.0
maxOutputTokensMaximum tokens in the responseModel default
topPNucleus sampling threshold1.0
That's a small slice of the config

GenerationConfig carries far more than these four — model fallback lists and routing filters, provider preferences and price ceilings, reasoning options, tool definitions and execution policy, response format, plugins, timeouts, and more.

Browse the complete schema, field by field, on Update Default Generation Config in the API reference — expand generationConfig to see every field with its type and constraints.

Available Models

Set model — or the models fallback list — to a model from the platform allowlist. The canonical list, with the exact rejection error and the rule for OpenRouter variant suffixes, lives in Model Routing → Allowed models.

The platform accepts a curated set, not the full OpenRouter catalog: requesting anything outside it fails immediately with MODEL_INVALID. See Model Routing & Pre-Filter for capability-based filtering within that set.

Reasoning

Models that support chain-of-thought reasoning (e.g., google/gemini-3.1-pro-preview, anthropic/claude-sonnet-5) can expose their internal thinking process. Configure reasoning via the reasoning_options field on the generation config:

curl -X POST https://api.travila.ai/api/v1/llm/update-default-generation-config \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"conversationKey": "support-chat-001",
"defaultGenerationConfig": {
"model": "google/gemini-3.1-pro-preview",
"reasoning_options": {
"effort": "EFFORT_MEDIUM",
"includeReasoningHistory": true
}
}
}'
FieldDescriptionDefault
effortHow much reasoning the model should perform. Values: EFFORT_NONE, EFFORT_MINIMAL, EFFORT_LOW, EFFORT_MEDIUM, EFFORT_HIGH, EFFORT_XHIGHEFFORT_UNSPECIFIED (provider default)
maxTokensMaximum tokens the model may use for reasoningModel default
excludeIf true, reasoning content is not included in the responsefalse
includeReasoningHistoryInclude reasoning from previous turns in multi-turn requests for provider continuitytrue

When reasoning is enabled, assistant messages may contain content parts with type: CONTENT_PART_TYPE_REASONING alongside the normal CONTENT_PART_TYPE_TEXT parts. The reasoning parts contain the model's internal thinking process.

Agent Profiles

An agent profile is a saved, versioned bundle of agent configuration — system prompt, model, tools — that you point a conversation at instead of assembling the same generation config on every call.

Two separate things, on two different APIs:

  • Managing profiles — create, edit, version, delete — is the Agent Profile APIs, or the admin console.
  • Selecting one for a conversation is the LLM APIs, covered below.
Managing profiles authenticates differently

Profiles are tenant configuration, not per-user data, so the Agent Profile APIs take a secret key on its own — no X-On-Behalf-Of, no end-user JWT. That is the opposite of every call on this page, where a bare sk_… key returns 401 authenticated user_id is required.

Create one, then point conversations at it by id:

curl -X POST https://api.travila.ai/api/v1/agent-profiles/create \
-H "X-API-Key: sk_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"profile": {
"profileId": "nutrition_coach",
"name": "Nutrition Coach",
"whenToUse": "Use when the user asks about food, meals, or macros.",
"enabled": true,
"generationConfig": {
"model": "google/gemini-3.6-flash",
"systemPrompt": "You are a nutrition coach. Be concise and practical."
}
}
}'

Set the profile when the thread is created:

{
"title": "Nutrition check-in",
"activeProfileId": "nutrition_coach"
}

Or switch profiles mid-conversation. setActiveProfileId on send-message or send-message-sync applies to that turn and every turn after it, until you set a different one:

{
"conversationKey": "thread_abc",
"userMessage": { "role": "ROLE_USER", "content": [{"type": "CONTENT_PART_TYPE_TEXT", "content": "..."}] },
"setActiveProfileId": "profile_escalation"
}
note

A profile's mcpServers replaces the conversation's MCP server list rather than merging with it — including when the profile's list is empty. If a profile is active and defines no MCP servers, the conversation has none for that turn.

Conversation Settings

Update the conversation's system prompt, interrupt policy, and other settings.

curl -X POST https://api.travila.ai/api/v1/llm/update-settings \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"conversationKey": "support-chat-001",
"settings": {
"system_prompt": "You are a helpful customer support agent for Acme Corp.",
"interruptPolicy": "QUEUE"
}
}'

System Prompt

The systemPrompt is prepended to every LLM request for this conversation. Use it to set the AI's persona, rules, and context.

Interrupt Policy

Controls what happens when a user sends a new message while a generation run is already in progress:

PolicyBehavior
QUEUEQueue the new message and process it after the current run completes
INTERRUPTCancel the current run and start a new one with the latest message

Context Management

For long conversations, the message history can exceed the model's context window. Context management settings control what happens then. Pick a strategy, then configure the matching sub-object.

StrategyConfig fieldBehaviour
CONTEXT_STRATEGY_COMPACTIONcompactionConfigSummarize older messages, keeping the recent ones verbatim
CONTEXT_STRATEGY_WINDOWINGwindowingConfigDrop everything beyond the most recent N messages
CONTEXT_STRATEGY_NONEDo nothing; the turn fails if it exceeds the window
curl -X POST https://api.travila.ai/api/v1/llm/update-context-management-settings \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"conversationKey": "support-chat-001",
"contextManagementSettings": {
"strategy": "CONTEXT_STRATEGY_COMPACTION",
"compactionConfig": {
"mode": "COMPACTION_MODE_ASYNC",
"threshold": {"percentage": 80},
"preserveRecent": 10
}
}
}'

threshold takes one of tokenCount (an absolute limit) or percentage (of the model's context window). preserveRecent is how many recent messages stay verbatim. COMPACTION_MODE_ASYNC compacts out of band so the turn is not delayed; COMPACTION_MODE_SYNC blocks the turn until compaction finishes.

Windowing is the cheaper option when losing old context is acceptable:

{
"conversationKey": "support-chat-001",
"contextManagementSettings": {
"strategy": "CONTEXT_STRATEGY_WINDOWING",
"windowingConfig": {"maxMessages": 50}
}
}

selectiveExclusionConfig composes with either strategy, and is the cheapest win of the three — dropping tool results and images from context often saves more tokens than summarizing prose does:

{
"conversationKey": "support-chat-001",
"contextManagementSettings": {
"strategy": "CONTEXT_STRATEGY_COMPACTION",
"selectiveExclusionConfig": {
"excludeToolResults": true,
"excludeImages": true,
"excludeReasoning": true
}
}
}

Compacting on Demand

Compaction normally fires on the configured threshold. Trigger it yourself when you know a long conversation is about to resume — at app launch, say — so the user does not pay the latency mid-turn.

curl -X POST https://api.travila.ai/api/v1/llm/compact-conversation \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{"conversationKey": "support-chat-001"}'

Response:

{
"compactionId": "cmp_a1b2c3d4",
"tokensBefore": 48211,
"tokensAfter": 12004,
"tokensSaved": 36207,
"durationMs": "4120",
"status": "COMPACTION_STATUS_COMPLETED"
}

status is COMPACTION_STATUS_PENDING when the conversation is configured for COMPACTION_MODE_ASYNC — the token counts are then the pre-compaction figures, and the result lands later. durationMs is a 64-bit integer, so it arrives as a string.

Prompt Variables

A profile's system prompt can carry {{.variable}} placeholders declared in its variableSpecs. Prompt variables are where the values come from — set on the conversation, re-rendered into the prompt on every subsequent turn, so a value you set once stays current without resending it.

curl -X POST https://api.travila.ai/api/v1/llm/update-prompt-variables \
-H "X-API-Key: sk_your_key_here" \
-H "X-On-Behalf-Of: user_123" \
-H "Content-Type: application/json" \
-d '{
"conversationKey": "support-chat-001",
"variables": {
"userName": "Jane",
"planTier": "pro"
}
}'

Response: {"settings": {...}} — the merged conversation settings.

This is a merge, not a replace: variables you do not send keep their current values. Pass updateMask to restrict the write to named variables:

{
"conversationKey": "support-chat-001",
"variables": {"planTier": "enterprise"},
"updateMask": "planTier"
}

Because rendering happens per turn, updating a variable mid-conversation changes the prompt for the next turn — this is the late-binding hook for anything that drifts during a session (a plan upgrade, a changed goal, the user's current screen).