Context
A shared dictionary holds data for middleware, prompts, and tools throughout the agent run.
On this page
What is Context?
A shared, mutable dictionary that flows through the entire agent run
The context is a Python dictionary that is created at the start of every agent run. It is pre-populated with system metadata and the incoming connector payload, then can be read and written by middleware, tool hooks, and tools. Values stored in context can also be referenced in the system prompt using {var} template syntax. The full context is stored with the run.
How Context Flows
The Context Dictionary
# The context dict is shared across the entire run
context = {
# System metadata (pre-populated automatically)
"run_id": "uuid-string",
"agent_name": "assistant",
"connector_id": "uuid-string",
"timestamp": "2025-01-15T10:30:00Z",
# Original connector payload (available in before(), tools, and after())
"payload": {
"user_id": 123,
"user_name": "Peter",
"question": "How do I update my billing details?"
},
# Webhook runs only: the HTTP request that started the run
"request": {"method": "POST", "headers": {...}, "query": {}, "body_base64": "..."},
# Your custom values (set in middleware or tools)
"user_name": "Peter",
"user_id": 123,
# Added automatically after agent completes (available in after() hook)
"token_usage": {
"input_tokens": 150,
"output_tokens": 200,
"thinking_tokens": 0,
"cached_input_tokens": 0,
"total_tokens": 350
},
"duration_ms": 1234.5
}System fields (run_id, agent_name, connector_id, timestamp) and payload are set automatically. Webhook runs also carry the HTTP request for checking the sender. Add any required custom key-value pairs.
Context in Middleware
Both the before() and after() hooks receive the context as their second parameter. Use context["payload"] in before() to read webhook JSON bodies, form fields, GET query parameters, and other connector input. Use before() to set values and after() to read the final state including any values set by tools during the run.
from typing import Any, Dict
async def before(content: Dict[str, Any], context: Dict[str, Any]) -> Dict[str, Any]:
"""Set values on context that are available everywhere."""
# Read request data from the original connector payload.
payload = context.get("payload", {})
# Copy selected values into top-level context so prompts can reference
# them as {user_name}, {user_id}, and {subscription_tier}.
context["user_name"] = payload.get("user_name", "there")
context["user_id"] = payload.get("user_id")
# Store additional request data for prompts/tools.
context["subscription_tier"] = payload.get("subscription_tier", "free")
return content
async def after(response: str, context: Dict[str, Any]) -> str:
"""Read values from context, including those set by tools."""
# Access system metadata
run_id = context.get("run_id")
duration = context.get("duration_ms")
# Access values set by tools during the run
api_calls_made = context.get("api_calls_made", 0)
return responseContext in Tools
To access context in a tool, add an optional context parameter to the function signature. connic supplies the value. The parameter is hidden from the LLM, so it will not appear in the tool schema and the model will never try to fill it.
from typing import Any, Dict
async def lookup_customer(email: str, context: Dict[str, Any]) -> dict:
"""Look up a customer by email in the CRM.
Args:
email: The customer's email address
Returns:
Customer details from the CRM
"""
# Read values set by middleware
user_id = context.get("user_id")
tier = context.get("subscription_tier", "free")
# ... perform the lookup ...
customer = {"email": email, "name": "Jane Doe", "plan": tier}
# Write values back to context for other tools or the after() hook
context["api_calls_made"] = context.get("api_calls_made", 0) + 1
context["last_customer_lookup"] = email
return customerThe context parameter is optional. Add it only when a tool needs shared run data.
Context in Prompts
Any value in context can be referenced in the agent's system_prompt using {variable_name} syntax. Variables are substituted at runtime before the prompt is sent to the model.
version: "1.0"
name: assistant
model: connic/gpt-5.6-terra
description: "Support assistant with user context"
system_prompt: |
You are a support assistant for {user_name} (ID: {user_id}).
Their subscription tier is {subscription_tier}.
Always address the user by name and tailor your responses
to their subscription level.
tools:
- crm.lookup_customer# System prompt template
system_prompt: |
Hello {user_name}, your account ID is {user_id}.
# If before() set context = {"user_name": "Peter", "user_id": 123}
# The agent sees:
# "Hello Peter, your account ID is 123."
# Unmatched placeholders are left as-is:
# {unknown_var} stays as {unknown_var} in the promptSafe substitution: If a placeholder like {unknown_var} has no matching context value, it is left as-is in the prompt. No errors are raised.
Full Example: End-to-End Flow
A complete example showing how context flows from middleware through prompts, tools, and back to the after hook.
# 1. middleware/assistant.py - Derive context values from the payload
async def before(content, context):
payload = context.get("payload", {})
context["user_name"] = payload.get("user_name", "there")
context["user_id"] = payload.get("user_id")
context["locale"] = payload.get("locale", "en-US")
return content
# 2. agents/assistant.yaml - Reference in prompts
# system_prompt: "Assist {user_name} (locale: {locale})"
# 3. tools/billing.py - Read and write context
async def get_invoice(invoice_id: str, context: dict) -> dict:
user_id = context.get("user_id") # Read from middleware
context["last_invoice"] = invoice_id # Write for after() hook
return {"invoice_id": invoice_id, "user_id": user_id}
# 4. middleware/assistant.py - Access everything in after()
async def after(response, context):
# context contains: run_id, agent_name, user_name, user_id,
# locale, last_invoice, token_usage, duration_ms
return responsePersistence
After the run completes, the full context dictionary (system metadata + custom values) is saved to the run log. It is available in the dashboard run details and through the API.