Prerequisites. A VisIQ account (sign in) with a
harness key from Settings → Harness Keys, Python 3.10+, and a model
provider key for Google ADK (the sample calls a hosted model — any provider
works). Full setup and fixes: Before you start ·
Troubleshooting.
visiq.govern(). VisIQ installs itself at ADK’s own guardrail surface, the
agent’s tool-callback chain, which every tool call ADK dispatches passes
through. There are no per-tool wrappers: every tool on the agent is governed,
including tools you add later, toolsets and MCP tools, and the tools of its
sub-agents. 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 crashing. A mask
hands your function only the redacted arguments. 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 model
object) is withheld rather than passed through.
Your own callbacks keep working. govern() does not overwrite
before_tool_callback or after_tool_callback. Whatever you set there, before
or after calling govern(), runs as ADK documents it, and VisIQ composes
around it: your before-callbacks run first and VisIQ decides on the arguments
the tool will actually receive, and for a retrieval tool VisIQ governs the
result your after-callbacks hand back, which is what the model sees.
Multi-agent systems. Call govern() on the root. It walks sub_agents
(including workflow agents such as SequentialAgent) and agents wrapped in an
AgentTool, and governs every LLM agent it finds under one agent identity. A
sub-agent you attach after that call is governed once you call govern() on
the root again.
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. ADK
still dispatches the tool itself exactly as it would without VisIQ.
Run this on AWS Bedrock
Google ADK has no native Bedrock provider — it reaches Bedrock through its documentedLiteLlm model wrapper, which ships in an extra rather than in the
base package:
ImportError: LiteLLM support requires: pip install google-adk[extensions] — the
base google-adk install at the top of this page is not enough for Bedrock.
Then swap the model= string for a LiteLlm instance. The govern() call is
unchanged:
The model id carries a
bedrock/ prefix. It is
bedrock/amazon.nova-micro-v1:0, not the bare amazon.nova-micro-v1:0 — the
prefix is what routes the call to Bedrock.AWS_PROFILE, instance role,
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY). Governance is untouched: the
tool-callback chain 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
— with an ungoverned control arm that had to leak for the run to count.
The same LiteLlm wrapper reaches other providers too: LiteLlm(model="openai/gpt-4o-mini")
runs the agent on OpenAI, with governance unchanged.
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 callback 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). SetVISIQ_FAIL_MODE=closedto 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_requireddecision 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
maskdecision runs the tool with the named arguments redacted; retrieval redaction masks document fields before the model sees them.
What
govern() does not reach. A runner plugin (Runner(plugins=[...]))
runs ahead of agent callbacks, and one whose after_tool_callback replaces a
tool’s result makes ADK skip the agent’s after-callbacks, so that replaced
result is not retrieval-governed. Model-native built-in tools that execute on the
provider’s side (Gemini’s google_search, code_execution) never pass through
ADK’s tool dispatch. A Workflow graph is not an agent, so call govern() on
each LlmAgent node instead. 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.