Accessing the RunContext
The RunContext is accessible from any callable within a Runnable’s execution usingget_run_context(). This includes:
- Main handlers: The main function that does the work (i.e. the function you pass to a Tool).
- Default parameter callables: Functions used to compute default values at runtime (as shown in Runnables).
- Lifecycle hooks: Functions that run before or after the main handler.
RunContext.current_span() method returns the span object for the currently executing Runnable, containing all execution data - input parameters, output, timing, metadata, and any custom data you store on it. You get direct access to the live span object being built during execution.
Here’s a simple example showing context access from a main handler:
Beyond
current_span(), the RunContext provides .parent_span() and .step_span() for the parent runnable and for workflow steps. Workflow wiring is on Control flow.Lifecycle Hooks
Beyond the main handler, Runnables support lifecycle hooks - functions that run at specific points during execution. These provide structured access points for context interaction and enable powerful data transformation patterns. Every Runnable supports two optional hooks. Both are parameterless.pre_hook: Runs after Pydantic has validated the call and after the approval gate, and only when the handler is actually going to run.post_hook: Runs after the handler completes.
What a pre-hook can change
A tool handler receives the kwargs that already passed validation. Those kwargs are fixed before the hook runs. Writing tospan.input inside the hook updates the span record, and the handler still receives the validated kwargs. A required parameter the caller omitted fails validation, so the hook never runs. Supply defaults with default_params (applied before validation) and normalize values inside the handler.
An agent is different. Agent.resolve_memory reads span.input after the pre-hook, so an agent pre-hook that sets span.input["prompt"] changes the user message for that turn.
- State initialization: timestamps, request ids, and other metadata stored on the span
- Observation: record the validated input for logging before the handler runs
- Agent prompts: adjust
span.input["prompt"]beforeresolve_memorybuilds the user message
Post-hooks: Processing Output After Completion
Apost_hook runs after the handler and can read the input and the output. Assigning span.output replaces the handler’s return value. collect() returns that assigned value.
Output replacement: Assigning
span.output in a post-hook replaces the handler’s return value. collect() returns the assigned value. Use this to transform results or apply a fixed response shape.- Logging: Record execution details and results
- Metadata Storage: Store processing metrics, timestamps, or analysis data
- Output Modification: Transform or enrich the final result
- Cleanup Tasks: Handle resource cleanup or state management
Using Agents in Hooks
When you use an Agent inside apre_hook or post_hook, you need to call .nest() to establish the proper hierarchical path for tracing and context management. This ensures the agent’s execution is correctly nested under the parent agent’s path.
Agents used as tools within another agent are automatically nested. However, agents used in hooks require manual nesting.
.nest() method updates the agent’s path hierarchy, ensuring proper tracing structure (e.g., agent.agent_is_company instead of just agent_is_company) and correct span nesting under the parent. Nested agents still run with isolated memory — they do not inherit the parent’s conversation history (see Nested Agent Memory).
Early Exit with bail()
Usebail() to exit early from any Runnable execution when validation fails or conditions aren’t met. The bail() function raises an EarlyExit error that stops execution of the current runnable.
You can use bail() in:
- Handlers: Exit early from tool or agent handlers
- Hooks: Exit early from pre_hook or post_hook functions
- Default parameter callables: Exit early when computing default values