Runtime Controls
Execution limits, coordinated concurrent runs, persistent sessions, and shared configuration across agent families.
On this page
Execution limits and retries
max_concurrent_runs: 10
max_iterations: 50
timeout: 180
retry_options:
attempts: 3
attempt_timeout: 120
initial_delay: 10
max_delay: 30
# Tool and sequential agents only:
rerun_middleware: truemax_concurrent_runscaps simultaneous runs, subject to the 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. It is capped by your plan’s run timeout, listed on the pricing page.retry_optionsapplies to individual model requests in an LLM run. All failures of those requests use the configured retry or fallback policy, including request timeouts and provider rejections. A file type the model does not accept (unsupported_file_type) is not retried on the same model but can still switch to the fallback. Completed tools and middleware keep their results. Tool and sequential agents retain operation-level retries.attemptsdefaults to 3 and allows 1–10 attempts, including the first. Without a fallback, this is the primary model’s budget. With a fallback, the primary gets one attempt and the fallback gets this budget. Configured context compression can add one repair request.attempt_timeoutdefaults to 120 seconds and must be a positive, finite number. Each completion or stream can use at most this time or the run’s remaining time, whichever is shorter. The run’s deadline is shared by all attempts and backoff waits; it is never divided by the attempt count or reset by a retry.- Same-model retries use exponential backoff with equal jitter: a random delay between half and all of the capped backoff.
initial_delaydefaults to 10 seconds andmax_delayto 30. A valid providerRetry-Afterreplaces this generated delay. A fallback switch is immediate. If the required wait cannot fit before the run’s deadline, no further request starts. rerun_middlewareonly affects operation-level retries on tool and sequential agents. Model-request retries keep the current LLM run and middleware state. Provider SDK retries are disabled so they do not multiply these attempts.
With the example above, a response taking 90 seconds succeeds on the first attempt. If an attempt reaches 120 seconds, subsequent attempts share the time left in the 180-second run.
The stream timeout covers the entire response; incoming chunks do not reset it. Once a request has delivered output, an interruption is reported as an incomplete response and the request is not restarted. Cancellation and the run’s deadline also stop further attempts. These rules apply to ordinary LLM streaming; native voice sessions have a separate lifecycle.
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: connic/gpt-5.6-terra
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: dropCoalesce mode
When another event arrives for an active key, its run waits as in queue mode, but only one run per key can wait. A newer event replaces the waiting run, so a burst of events during a long run leads to a single follow-up run with the latest payload. Use this when every event asks the agent to re-check the same state.
The replaced run is cancelled. Its context contains superseded_by_concurrency_rule and superseded_by, the ID of the run that replaced it.
version: "1.0"
name: process-agent
type: llm
model: connic/gpt-5.6-terra
description: "Re-evaluates the current process step on every status event"
system_prompt: "Check the current step of the process and act on it."
# Events that arrive during a run collapse into one follow-up run.
concurrency:
key: "process_id"
on_conflict: coalesceKey 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. Runs waiting for their key do not take a slot.
Waiting runs
- Waiting runs are persisted. They survive restarts and deployments and start on the active deployment.
- A key stays held during a deployment. A run still finishing on the previous deployment keeps its key until it ends.
- A run paused for an approval keeps its key. After the decision, it resumes before any waiting run.
- In queue mode, waiting runs start in the order their events arrived.
- There is no limit on how many runs can wait and no wait timeout. Waiting time does not count toward
timeout, and a run uses no Project credit before it starts. Runs cancelled bydroporcoalescenever start.
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
Set session: true for one shared session across the agent’s runs. An object without key or with key: null uses the same shared session. false, null, or omitting session disables persistence.
version: "1.0"
name: support-bot
type: llm
model: connic/gpt-5.6-terra
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: connic/gpt-5.6-luna
keep_recent_messages: 12
# Optional early compression based on model-reported prompt usage
max_prompt_tokens: 100000History and browser state
history and browser both default to true. This example retains cookies and local storage for each chat while starting every run with fresh conversation history. With browser: false, browser tools still work but start with fresh browser state.
session:
key: context.chat_id
ttl: 86400
history: false
browser: trueSession key
The optional key separates sessions by a resolved value. When provided, it must use one of two prefixes:
context.<path>resolves from middleware context, including keys derived from request data.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 ttl expires 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.
Runs that share a session are not serialized. If two runs for the same session overlap, the run that writes second fails. When that can happen, add a concurrency rule on the field that identifies the session, for example concurrency.key: conversation_id with session.key: input.conversation_id.
Context compression
Enable context_compression to shorten conversation history when a provider reports that the context window is full. connic compresses before switching to a fallback, then makes one additional request to the same model with the shortened history. Each model call in the agent loop allows at most one such repair request, outside the normal attempt count. It keeps the original run deadline and the attempts already used. If repair fails, the normal retry or fallback policy continues. Set context_compression.model to use a separate summary model; the repair request uses the model that rejected the context. Set max_prompt_tokens to compress earlier using reported prompt usage. Use session_history.interval when stored history should also be compacted between runs.
Stored history has no limit on total size or number of runs; each stored message can be up to 5 MB. With session_history.interval: 4, every fourth run ends by summarizing older history and keeps the last keep_recent_runs runs (default 1) verbatim. Without it, every run loads the full stored history, and compression only shortens the request, not the stored session.
If a configured key path resolves to an empty or missing value, the run fails. Omitting the key uses the agent’s shared session.
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.
connic combines defaults shallowest-first, then applies the agent file so its values win 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 to 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,retrieval,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.approval.inputsdeduplicates by input-tool name; a deeper declaration replaces the inherited configuration for that name.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: connic/gpt-5.6-terra
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.
connic dev provides a cloud development environment with hot reload.