Skip to main content
Prerequisites. A VisIQ account (sign in) with a harness key from Settings → Harness Keys, Python 3.10+ (CrewAI’s own floor), and a model provider key for CrewAI (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 a CrewAI crew by passing it to visiq.govern(). There are no per-tool wrappers: every tool on every agent in the crew is governed, including tools passed to a single Task(tools=[...]), tools you append to an agent after calling govern(), and the delegation and memory tools CrewAI adds at run time. You can also govern a single Agent, which covers that agent in any crew and under agent.kickoff(). 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

Verified against crewai 1.15.2.

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 crew

govern() returns the same object, so it also works as an expression. It is idempotent: governing a crew or agent twice installs governance once. To govern one agent rather than a whole crew, pass the agent: govern(support, agent_id="support-bot"). Every tool call the model makes 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 the crew carries on instead of crashing. A mask hands your function only the redacted arguments, nested ones 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. Both tool styles are governed: @tool functions and BaseTool subclasses. They reach their code through different callables (a @tool tool’s run never goes through _run), so VisIQ wraps the one each style actually executes, and a call is decided exactly once whichever dispatch path CrewAI takes: native function calling or the text (ReAct) loop.
CrewAI caches tool results and serves a repeated call from that cache without running the tool. A cached answer would skip the policy decision and the audit row, so caching is turned off for governed tools: every call is decided afresh. An async tool is decided in a worker thread, off your event loop, and then awaited in your own task.
On the first kickoff the crew’s whole tool surface is registered with VisIQ, and each run’s decisions are delivered to the dashboard when that run ends, including a run that fails.

Run this on AWS Bedrock

CrewAI reaches Bedrock through its own LLM wrapper, which routes to LiteLLM’s bedrock/ provider, so there is no adapter package and the govern() call is unchanged:
Hand that llm to your agents. Note the bedrock/ prefix on the model id: that prefix is what selects the provider. Credentials come from the standard AWS chain (AWS_PROFILE, instance role, AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY). Governance is untouched: the gate fires at the same point, the same rules match, the same rows land in the audit trail. Verified end to end against real Bedrock inference. 15 of 15 Bedrock scenario checks passed. Deploying to Bedrock AgentCore Runtime needs nothing extra either: it hosts your process, so install the visiq wheel in your image and set VISIQ_API_KEY in the runtime environment. If instead you use a managed harness, AWS owns the agent loop and this in-process governance 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. crew.kickoff_for_each(), crew.train() and crew.test() run on copies of your agents: their existing tools stay governed, but a tool CrewAI injects into a copy at run time is not, and the copies’ audit events are delivered in batches or at exit rather than per run. The manager agent CrewAI creates for Process.hierarchical is not governed (its delegation reaches your governed agents, whose tools are). A BaseTool subclass that overrides run itself, rather than _run, is not intercepted. A tool object shared between two separately governed crews keeps the first crew’s governance. Calling a tool function directly, outside an agent, is not an agent tool call. Need finer control than the whole crew? The per-call Governor.gate_tool primitive is documented in the Python SDK Reference.

Verify it’s working

Run the crew 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.