New to the adapters? Start with the wrapping overview and comparison
table.
Compatible versions: see the compatibility
table for the verified
openai-agents range.HexgateRunner
HexgateRunner is a drop-in replacement for agents.Runner. It wraps the
agent’s tools with a PolicyEnforcer at construction time and opens a HexgateContext
scope around each Runner.run / run_sync / run_streamed call so role
resolution happens at call time.
Under the hood
HexgateRunner.runcallswrap_openai_agent, which builds aPolicySetfor(api_key, agent.name, tool_names), constructs onePolicyEnforcer, and returns adataclasses.replace’d copy of the agent with policy-gated tool copies — your originalagentis untouched.- The runner opens an
async with hexgate_context:scope around the underlyingRunner.run*call. When the model calls a tool, the guard asksenforcer.decide(...)for aDecision. On non-allow, it returnsdecision.as_error_message()— a[policy_denied]or[approval_required]markered string the model can interpret and recover from. - The run executes inside
propagate_attributes(user_id=..., session_id=..., metadata={"user_roles": ...}), so Langfuse spans carry the caller identity.
run_sync and run_streamed work the same way.
Agent-level enforcement
Beyond tool calls,HexgateRunner enforces agent-level policy:
admission (may this caller run the agent) at run entry, handoff reach
(agent.handoff:<name>) at the SDK’s on_handoff seam — a denied handoff is
vetoed before the target runs — and agent-as-tool reach (agent.tool:<name>)
at the tool seam. Set HexgateRunner(max_handoff_depth=N) to cap a runaway
handoff chain.
Agent-as-tool reach is enforced at the top level. The SDK tags an
Agent.as_tool() with its target agent, so when the top-level agent’s policy
declares an agents block, that as-tool call is gated under agent.tool:<name>
(closed-world, via/constraints honored) rather than by tool name. A reach edge
one level deeper — a sub-agent that itself calls another agent as a tool — is not
gated yet, because the sub-agent runs unwrapped through the SDK’s own runner;
those deeper edges fall back to tool-name gating. On an agents SDK too old to
expose the tool origin, even the top level falls back to name-gating and a
declared via: tool rule warns at setup.Runnable example
examples/devops_openai.py — HexgateRunner (OpenAI Agents SDK) end-to-end.