Runtime Controls
Bound execution, coordinate concurrent runs, retain session history, and share configuration across agent families.
Execution limits and retries
max_concurrent_runs: 10
max_iterations: 50
timeout: 120
retry_options:
attempts: 5
initial_delay: 10
max_delay: 60
# Tool and sequential agents only:
rerun_middleware: truemax_concurrent_runscaps simultaneous runs, subject to your subscription limit.max_iterationslimits the LLM loop so repeated tool calls cannot run indefinitely.timeoutsets the maximum execution time in seconds, with a minimum of five seconds and a plan-level cap.retry_optionsretries the failing operation. LLM agents retry an individual model request and reflect failed tool calls without replaying the agent. Tool and sequential agents retain operation-level retries.attemptsincludes the first attempt and is limited to 10.- Model requests use capped exponential backoff with jitter unless the provider supplies
Retry-After. A value abovemax_delayfails without sleeping. rerun_middlewareonly affects operation-level retries on tool and sequential agents; LLM agents are never replayed.
Concurrency rules
Concurrency rules ensure that only one run per unique key is active at a time. Use them when an agent processes events for a specific support process, customer, or order and parallel processing would conflict.
Queue mode (default)
When another event arrives for an active key, it waits until the first run finishes and then starts automatically.
version: "1.0"
name: support-processor
type: llm
model: gemini/gemini-2.5-pro
description: "Processes support tickets one at a time per process"
system_prompt: "You are a support agent. Process the incoming ticket."
# Only one run per process_id at a time. Additional runs wait in queue.
concurrency:
key: "process_id"
on_conflict: queueDrop mode
When another event arrives for an active key, the new run is cancelled immediately. Use this when duplicate work would be wasteful.
version: "1.0"
name: notification-handler
type: tool
description: "Handles notifications, skipping duplicates"
tool_name: notifications.handle
# Drop duplicate runs for the same customer while one is active.
concurrency:
key: "data.customer_id"
on_conflict: dropKey extraction
The key uses dot notation to read the trigger payload. If a Kafka payload is {"data": {"customer_id": "abc"}}, use data.customer_id. If the path does not exist, concurrency enforcement is skipped for that run.
Interaction with max_concurrent_runs
Both constraints apply. With max_concurrent_runs: 5 and concurrency.key: "process_id", five process IDs can run in parallel, but only one run per process ID can be active.
Concurrency rules are not supported on sequential agents. The key comes from the raw trigger payload, so it applies uniformly to all trigger types, including Kafka, HTTP, Cron, API, and trigger_agent.
Persistent sessions
By default, every request creates an isolated session. Persistent sessions maintain conversation history across requests, restarts, and redeployments.
version: "1.0"
name: support-bot
type: llm
model: gemini/gemini-2.5-pro
description: "A support chatbot that remembers conversation history"
system_prompt: |
You are a helpful support agent. Use the conversation history
to provide contextual responses.
# Maintain persistent sessions keyed by chat ID from middleware
session:
key: context.chat_id
ttl: 86400 # Sessions expire after 24 hours of inactivity
# Keep long conversations within the model context window
context_compression:
enabled: true
# Optional model for compression summaries; defaults to the agent model
model: gemini/gemini-2.5-flash
keep_recent_messages: 12
# Optional early compression based on model-reported prompt usage
max_prompt_tokens: 100000Session key
The key identifies the session and must use one of two prefixes:
context.<path>resolves from the middleware context. This is recommended because middleware can derive a stable key from any part of the request.input.<path>resolves from the raw connector payload before middleware. It requires valid JSON and supports nested paths.
Set the key in middleware
async def before(content: dict, context: dict) -> dict:
# Extract a stable identifier for this conversation from the connector payload.
payload = context.get("payload", {})
context["chat_id"] = payload.get("chat_id")
return contentUse an input key
# When the connector payload is JSON like {"user_id": "u123", "message": "..."}
session:
key: input.user_idTTL and session management
The optional ttlexpires sessions after that many inactive seconds. The minimum is 60 seconds; without a TTL, sessions never expire. View and delete active sessions in the dashboard under Storage > Sessions. Sessions are scoped per environment.
Context compression
Add context_compression to keep long-running LLM sessions inside the model context window. Once configured, provider context-window errors trigger compression and an automatic retry. Set context_compression.model to use a separate summary model; normal agent calls and their retry still use the agent model. Set max_prompt_tokens to compress earlier using reported prompt usage. Use session_history.interval only when stored history should also be compacted between runs.
If the session key resolves to an empty or missing value, the run fails. Ensure the middleware or payload always provides it.
Cascading defaults with _defaults.yaml
Add _defaults.yaml to any directory under agents/ to share configuration with agents at that level and below. Use it for a common model, guardrails, tools, or database.collections.
The loader merges defaults shallowest-first, then applies the agent file last so the agent wins on conflict.
What can live in a defaults file
Defaults accept the same fields as agent YAML and may be partial, with two exceptions:
nameanddescriptionare forbidden because they identify a specific agent.versionis allowed so you can pin the schema version project-wide. The agent file must still set it together withnameanddescription.
Merge rules
- Scalars such as
model,temperature,system_prompt, andtimeoutare replaced by the deeper layer. - Objects such as
database,knowledge,retry_options,approval,session, andguardrailsmerge recursively by key. - Lists concatenate with deduplication:
tools,discoverable_tools, andapproval.toolsdeduplicate by tool reference; a deeper declaration overrides the inherited entry.mcp_serversdeduplicates by server name; a deeper full server configuration replaces the inherited one.guardrails.inputandguardrails.outputdeduplicate by rule name when present and otherwise append.- Sequential
agentsdeduplicate by string.
Example
version: "1.0"
type: llm
model: anthropic/claude-sonnet-4-6
temperature: 0
guardrails:
input:
- type: prompt_injection
mode: block
output:
- type: system_prompt_leakage
mode: block
tools:
- audit.log_eventversion: "1.0"
name: refund-agent
description: "Issues refunds against the billing system."
system_prompt: "Refund only valid charges. Use the tools."
tools:
- billing.lookup_charge
- billing.issue_refund
approval:
tools:
- billing.issue_refund: param.amount > 50
timeout: 3600The effective refund-agent inherits the model, temperature, and both guardrails. Its tools become [audit.log_event, billing.lookup_charge, billing.issue_refund].
Run connic lint to validate the merged configuration. A/B test variants named <base>-test-<name>.yaml inherit the same defaults as their base.
Use connic dev for a cloud dev runner with hot reload. Pair it with tests before shipping.