Skip to main content
Prerequisites. A VisIQ account (sign in) with a harness key from Settings → Harness Keys, Python 3.10+ (AutoGen’s own floor), and a model provider key for AutoGen (the sample calls a hosted model; any provider works). Full setup and fixes: Before you start · Troubleshooting.
Add action governance, retrieval governance, and a full audit trail to an AutoGen AgentChat agent by passing it to visiq.govern(). VisIQ installs itself at AutoGen’s own tool-execution seam: the run_json call the agent’s workbench makes on each tool. There are no per-tool wrappers to write. The visiq wheel, compiled from the same governance core as the TypeScript harness, makes every decision locally, in-process against a cached rule bundle.

Install

Set environment variables

.env
The visiq wheel reads its configuration from the process environment and does not auto-load a project .env. Export the variables (or load them yourself) before calling govern().

Govern your agent

govern() returns the same agent, so it also works as an expression. It is idempotent: governing an agent twice installs governance once. Every tool call is decided before the tool runs. A deny means your function is never called: the block message is returned as the tool’s result, so the model reads why and adjusts course instead of the run failing. A mask hands your function only the redacted arguments, nested values included. Tools named in retrieval_tools also have their result governed before it reaches the model, with restricted documents dropped and sensitive fields redacted. A result the retrieval facet cannot split into documents (a dict envelope, a pydantic model) is withheld rather than passed through.

Govern a team

Pass a team instead of an agent and every AssistantAgent participant is governed under one agent identity, including participants of nested teams:
A participant that is not an AssistantAgent (a CodeExecutorAgent, a UserProxyAgent, a SocietyOfMindAgent or your own BaseChatAgent subclass) has no tool calls for VisIQ to see, so it is not governed. govern() names each one on stderr rather than skipping it silently, and refuses a team with no AssistantAgent in it at all.
Governance decisions are local and synchronous, but they run off your event loop, so a human-approval hold cannot freeze the rest of your asyncio app. The tool itself still runs in AutoGen’s own task, so cancelling a run through its CancellationToken also cancels the tool it was running.
On an agent’s first turn its tool surface is registered with VisIQ, and each turn’s decisions are delivered to the dashboard when that turn produces its final response. That covers agent.run(), agent.run_stream(), on_messages() and every turn a team gives the agent.

Run this on AWS Bedrock

AutoGen reaches Bedrock through an extra, pip install "autogen-ext[anthropic]", which also needs boto3. The govern() call is unchanged; only the model client you hand your agent is different:
Unlike every other framework here, BedrockInfo takes explicit credentials: it does not read the ambient AWS chain (AWS_PROFILE, instance role), so pass the keys in yourself. Governance is untouched by the swap: the gate still decides before the tool body runs, the same rules match, and the same rows land in the audit trail. Verified end to end against real Bedrock inference. 15 of 15 Bedrock scenario checks passed — with an ungoverned control arm that had to leak for the run to count.
Three things to know before you run this.
  • AutoGen’s Bedrock transport is Anthropic-only. There is no first-party AutoGen path to Nova, Mistral, or Llama on Bedrock — use an anthropic.* model id, or reach those model lines through a different framework.
  • A first-time AWS account needs the Anthropic use-case form. Until it is submitted, every anthropic.* model returns “Model use case details have not been submitted for this account. Fill out the Anthropic use case details form before using the model.” It is a one-time per-account submission in the Bedrock console under Model access — not a quota, an IAM policy, or a region problem, and no retry clears it. Submit it from your AWS Organization management account and member accounts inherit it.
  • Use a current model, and its us. inference profile. After the form, anthropic.claude-3-haiku-20240307-v1:0 still fails with a different message — “marked by provider as Legacy and you have not been actively using the model in the last 30 days.” Reach the 4.5 models through their cross-region inference profile (us.anthropic.claude-haiku-4-5-20251001-v1:0); the bare model id is a ValidationException.
Deploying to Bedrock AgentCore Runtime needs nothing extra. It hosts your process, so install the harness in your image and set VISIQ_API_KEY in the runtime environment, and the govern() call travels with the code. If instead you use a managed harness, AWS owns the agent loop and this in-process gate does not apply; see AWS Bedrock for the two chokepoints that still work there.

What happens at runtime

New agents start in monitor mode (observe-only) until you flip them to enforce on the Control Agents → Agents page.
  • Decisions are local. The SDK fetches one cached rule bundle (GET /rules/bundle, ETag revalidation) and refreshes it in the background. Tool calls evaluate in-process; the only decision-path network call is waiting on a human approval.
  • Fail-open by default, loudly — strict deny is opt-in. Real policy outcomes always enforce: an explicit rule deny, the operator kill-switch, and an in-core mask/redact that cannot be applied (it downgrades to deny) all block. A harness-internal failure does NOT block: if the backend is unreachable or the governance core is unavailable, the harness proceeds UNGOVERNED with a loud [VisIQ] FAIL-OPEN (no-bundle) report on stderr, so a VisIQ outage never disrupts your agent (owner decision, 2026-07-15). Set VISIQ_FAIL_MODE=closed to block those harness-internal failures instead.
  • Deny blocks the call. The tool is never executed, and the model receives the block message as the tool result.
  • Approvals pause the call. An approval_required decision holds the tool while a human decides via Slack or Email (Microsoft Teams delivery is built server-side; its connector card is coming soon) — the SDK polls for up to 120 seconds (VISIQ_HITL_TIMEOUT_MS), then fails closed.
  • Mask proceeds, redacted. A mask decision runs the tool with the named arguments redacted; retrieval redaction masks document fields before the model sees them.
What govern() does not cover. Handoff tools (handoffs=[...]) are not governed: they only emit a handoff message, and blocking one would break the team’s control flow without stopping any side effect. Tools added to an agent after govern() by editing its internal tool list are not governed (AutoGen 0.7 has no public API for that; a custom or MCP workbench is governed at its call_tool, so whatever it lists at call time is covered). The tool object itself is governed, not a copy, so a FunctionTool shared with another agent stays governed there too. A tool function you call directly, outside the agent, is not an agent tool call. Need finer control than the whole agent? The per-call Governor.gate_tool primitive is documented in the Python SDK Reference.

Verify it’s working

Run the agent once, then open the dashboard:
  • Control Agents → Agents — your agent appears automatically (monitor mode) with a live last-seen heartbeat.
  • Control Agents → Runtime Enforcement — a decision row for every governed tool call, with the matched rule and outcome.

Next steps

Full Quickstart

All supported frameworks and what happens behind the scenes.

Python SDK Reference

The complete Governor API — gate_tool, gate_documents, fail modes.