Context¶
The context is a mutable object passed throughout an agent run.
Basic Context¶
from dataclasses import dataclass
from agents import Agent, Runner
@dataclass
class MyContext:
user_id: str
session_id: str
request_count: int = 0
context = MyContext(user_id="123", session_id="abc")
result = await Runner.run(agent, "Hello!", context=context)
Accessing Context in Tools¶
from agents import function_tool, RunContextWrapper
@function_tool
def get_user_data(ctx: RunContextWrapper[MyContext]) -> str:
"""Get data for the current user."""
user_id = ctx.context.user_id
return f"Data for user {user_id}"
@function_tool
def increment_count(ctx: RunContextWrapper[MyContext]) -> str:
"""Increment request count."""
ctx.context.request_count += 1
return f"Count: {ctx.context.request_count}"
Context in Instructions¶
Dynamic instructions based on context:
from agents import Agent, RunContextWrapper
def dynamic_instructions(ctx: RunContextWrapper[MyContext], agent: Agent) -> str:
user = ctx.context.user_id
count = ctx.context.request_count
return f"""You are helping user {user}.
This is request #{count} in this session.
Be concise and helpful."""
agent = Agent(
name="contextual",
instructions=dynamic_instructions,
)
Context in Guardrails¶
from agents import input_guardrail, InputGuardrailResult, RunContextWrapper
@input_guardrail
async def check_permissions(
ctx: RunContextWrapper[MyContext],
agent,
input_text: str
) -> InputGuardrailResult:
"""Check user permissions."""
if ctx.context.user_id not in allowed_users:
return InputGuardrailResult(
tripwire_triggered=True,
output_info="User not authorized."
)
return InputGuardrailResult(tripwire_triggered=False)
Context in Handoffs¶
from agents import handoff, Handoff, RunContextWrapper
@handoff
def conditional_handoff(ctx: RunContextWrapper[MyContext]) -> Handoff | None:
"""Hand off based on context."""
if ctx.context.user_id.startswith("vip_"):
return Handoff(target=vip_agent)
return None
RunContextWrapper¶
The wrapper provides additional functionality:
from agents import RunContextWrapper
@function_tool
def example(ctx: RunContextWrapper[MyContext]) -> str:
# Access your context
user = ctx.context.user_id
# Access run metadata
run_id = ctx.run_id
# Check current agent
agent_name = ctx.current_agent.name
return f"User: {user}, Run: {run_id}, Agent: {agent_name}"
Context Types¶
Dataclass (Recommended)¶
from dataclasses import dataclass, field
@dataclass
class AppContext:
user_id: str
permissions: list[str] = field(default_factory=list)
metadata: dict = field(default_factory=dict)
Pydantic Model¶
from pydantic import BaseModel
class AppContext(BaseModel):
user_id: str
permissions: list[str] = []
class Config:
extra = "allow" # Allow additional fields
Simple Dict¶
# Works but not type-safe
context = {"user_id": "123", "data": {}}
result = await Runner.run(agent, "Hello!", context=context)
Context Mutation¶
Context can be modified during the run:
@function_tool
def update_context(ctx: RunContextWrapper[MyContext], key: str, value: str) -> str:
"""Update context metadata."""
ctx.context.metadata[key] = value
return f"Updated {key}"
Context Persistence¶
For multi-turn conversations:
# Store context between requests
contexts: dict[str, MyContext] = {}
async def handle_message(session_id: str, message: str):
# Get or create context
if session_id not in contexts:
contexts[session_id] = MyContext(
user_id="user_123",
session_id=session_id,
)
context = contexts[session_id]
result = await Runner.run(agent, message, context=context)
# Context is updated in place
return result.final_output
See Also¶
- Tools - Using context in tools
- Guardrails - Context in guardrails
- Running Agents - Passing context