Skip to content

intutic_clawde.gate.adapters.autogen_workbench ​

Microsoft AutoGen adapter, in-process half: IntuticWorkbench.

autogen.py's IntuticInterventionHandler sees only runtime-routed messages. AssistantAgent (autogen_agentchat.agents._assistant_agent) never routes its own tool calls through the runtime: _execute_tool_call walks self._workbench and calls wb.call_tool(...) directly (wb.call_tool_stream(...) when the entry is a StaticStreamWorkbench). The workbench is therefore the in-process veto point, and this module wraps it.

IntuticWorkbench is a Workbench that delegates everything to the one it wraps and guards call_tool with Gate.guard(name, dict(arguments)), the same core pydantic_ai.py's IntuticWrapperToolset.call_tool uses. On deny it returns ToolResult(is_error=True) carrying the [Intutic Governance] BLOCKED: ... text rather than raising: AutoGen turns that into a FunctionExecutionResult the model reads on its next turn, so the run continues and the model can change approach, while the tool body never runs. Raising would abort the whole agent.run().

guard_assistant_agent(agent) wraps each entry of an existing AssistantAgent's _workbench list in place, idempotently.

Verified against autogen-core/autogen-agentchat 0.7.5:

  • Workbench.call_tool(self, name, arguments=None, cancellation_token=None, call_id=None) -> ToolResult.
  • _execute_tool_call dispatches on isinstance(wb, StaticStreamWorkbench); a wrapper that is not one goes through call_tool, so wrapping a StaticStreamWorkbench trades its intermediate streamed events for governance. The final ToolResult is unchanged.
  • Handoff tools (handoffs=[...]) are run through handoff_tool.run_json at _assistant_agent.py and never touch the workbench: they are not governed here. A handoff transfers control between agents and executes no user tool, so the reachable tool calls are still every one that goes through a workbench.

Optional import: this module imports without autogen-core; only instantiating IntuticWorkbench requires it (pip install intutic-clawde[autogen]).

Classes ​

IntuticWorkbench ​

python
class IntuticWorkbench(wrapped: Any, gate: Optional[Gate] = None)

Bases: Workbench

A Workbench that vetoes a tool call before the wrapped one runs it.

Usage:

python
from autogen_agentchat.agents import AssistantAgent
from autogen_core.tools import StaticWorkbench
from intutic_clawde.gate.adapters.autogen_workbench import IntuticWorkbench

agent = AssistantAgent(
    "helper", model_client,
    workbench=IntuticWorkbench(StaticWorkbench([my_tool])),
)

gate overrides the process-wide instance registered with install().

Attributes ​

NameTypeDefaultDescription
component_provider_override—'intutic_clawde.gate.adapters.autogen_workbench.IntuticWorkbench'
component_type—'workbench'

Methods ​

IntuticWorkbench.call_tool() ​
python
async def call_tool(
    name: str,
    arguments: Mapping[str, Any] | None = None,
    cancellation_token: Any = None,
    call_id: str | None = None,
) -> Any
IntuticWorkbench.list_tools() ​
python
async def list_tools() -> Any
IntuticWorkbench.load_state() ​
python
async def load_state(state: Mapping[str, Any]) -> None
IntuticWorkbench.reset() ​
python
async def reset() -> None
IntuticWorkbench.save_state() ​
python
async def save_state() -> Mapping[str, Any]
IntuticWorkbench.start() ​
python
async def start() -> None
IntuticWorkbench.stop() ​
python
async def stop() -> None

Functions ​

guard_assistant_agent() ​

python
def guard_assistant_agent(agent: Any, gate: Optional[Gate] = None) -> List[Any]

Wrap every workbench an AssistantAgent holds in an IntuticWorkbench.

Edits agent._workbench in place (the list _execute_tool_call walks) and returns it. Idempotent: an entry that is already an IntuticWorkbench is left alone. The agent must have been built with tools= or workbench=; an agent with no workbench has nothing to govern and is returned unchanged.

The circuit breaker for AI agents