Framework Integrations
Connecting an agent to Suvra is four steps:
- Create a
Suvraclient — registers the agent with the Control Plane. - Pass it to your framework adapter — wraps tool calls so policy is enforced before execution.
- Confirm the agent appears in the dashboard at
/dashboard/agents. - Run one guarded tool call to see policy decisions and audit entries flow.
1. Create a Suvra client
import os
from suvra import Suvra
suvra = Suvra(
url="https://suvra.example.com",
agent_id="customer-support-agent",
tenant_id="your-tenant-id",
agent_name="Customer Support Agent",
framework="langchain",
purpose="Handles customer support workflows",
risk_tier="medium",
auth_token=os.environ["SUVRA_AUTH_TOKEN"],
)
agent_id and tenant_id (for remote mode) are required. Everything else is recommended for governance and audit visibility.
Auth: If
SUVRA_AUTH_TOKENis configured on the Control Plane, passauth_token=...or setSUVRA_AUTH_TOKENin the agent runtime environment. Without it, agent registration may fail.
Advanced metadata: For fields like
tools_used,data_classes_touched,approval_profile, orpolicy_id, pre-register or update the agent through the/agents/{agent_id}/registeror/agents/{agent_id}API.
2. Pass the client to your framework adapter
Pick the example for the framework you actually run.
LangChain
from suvra.integrations.langchain import SuvraCallbackHandler, SuvraGuardRunnable
callbacks = [SuvraCallbackHandler(suvra, fail_closed=True)]
guarded = SuvraGuardRunnable(suvra, runnable, "search", fail_closed=True)
Claude Agent SDK (Anthropic)
from suvra.integrations.anthropic import suvra_hook, suvra_agent_options
hook = suvra_hook(suvra, fail_closed=True)
options = suvra_agent_options(suvra, fail_closed=True)
Use the Reference section below only for the framework you run.
3. Confirm the agent appears in the dashboard
Open /dashboard/agents. Your agent appears after registration. Enforcement activity and heartbeats are visible through the audit, node, and agent views depending on your deployment mode.
4. Run one guarded tool call
Trigger the agent's normal flow. The first guarded call:
- creates an audit entry with the policy decision and
params_hash - routes through Approvals if the policy returns
needs_approval - is blocked (and surfaced to the agent) if the policy returns
deny
How agent connection works
When you instantiate Suvra(url=..., agent_id=...), the client registers the agent immediately via PUT /agents/{agent_id}/register. The same client then enriches actions with agent_id, framework, node, workspace, and environment context.
Framework adapters do not handle registration. They handle action-level enforcement after registration — every guarded tool call is policy-evaluated, audited, and (when needs_approval) brokered through the Control Plane.
All adapters use lazy imports — Suvra does not depend on framework packages at install time.
Pre-register an agent via API
Useful from a deployment pipeline so the agent exists in the dashboard before the first runtime connection:
curl -X PUT https://suvra.example.com/agents/my-agent/register \
-H "Content-Type: application/json" \
-H "X-Suvra-Token: $SUVRA_AUTH_TOKEN" \
-d '{
"agent_id": "my-agent",
"owner": "platform-team",
"purpose": "Q4 report generator",
"status": "active",
"risk_tier": "medium",
"approval_profile": "strict",
"runtime_type": "python",
"framework": "langchain",
"tools_used": ["web_search", "database_query"],
"data_classes_touched": ["PII", "financial"]
}'
The body's agent_id must match the path. See Agents for the full registration schema, env-var auto-resolution, and validation rules.
Reference: per-framework adapters
Suvra ships thin framework adapters in suvra.integrations.*. Each wraps the framework's native tool / callback surface so every tool call is validated before it runs.
All examples below assume you have a
Suvraclient instantiated as shown in step 1.
Claude Agent SDK (Anthropic)
from suvra.integrations.anthropic import suvra_hook, suvra_agent_options
hook = suvra_hook(suvra, fail_closed=True)
options = suvra_agent_options(suvra, fail_closed=True)
suvra_hook(suvra, *, fail_closed=False)— asyncPreToolUsehook. Rejects tool calls whosedecision != allow. On Suvra errors, returns empty unlessfail_closed=True.suvra_agent_options(suvra, *, fail_closed=False)— convenience dict you can merge intoClaudeAgentOptions(...)so the hook is registered.
LangChain
from suvra.integrations.langchain import SuvraCallbackHandler, SuvraGuardRunnable
callbacks = [SuvraCallbackHandler(suvra, fail_closed=True)]
guarded = SuvraGuardRunnable(suvra, runnable, "search", fail_closed=True)
Signature: SuvraGuardRunnable(suvra, inner, action_type, *, fail_closed=False)
SuvraCallbackHandler— aBaseCallbackHandlerthat interceptson_tool_startand cancels tool execution on deny.SuvraGuardRunnable— wraps any LangChainRunnableand validates the input payload as a Suvra action before invoke.
CrewAI
from suvra.integrations.crewai import suvra_before_tool_call, suvra_after_tool_call
crew = Crew(
...,
before_tool_call=suvra_before_tool_call(suvra, fail_closed=True),
after_tool_call=suvra_after_tool_call(suvra),
)
suvra_before_tool_callreturnsFalseto block a tool call;Noneto allow.suvra_after_tool_callrecords the executed outcome for audit correlation.
AutoGen
from suvra.integrations.autogen import guard_tool, guard_function_map
@guard_tool(suvra, action_type="fs.write_file", fail_closed=True)
def write_report(path: str, content: str):
...
agent.register_function(guard_function_map(suvra, function_map, fail_closed=True))
guard_tool(suvra, action_type, *, fail_closed=False)— decorator that validates before each invocation. Builds action params from the function's bound arguments.guard_function_map(suvra, function_map, *, fail_closed=False)— wraps every callable in an existingfunction_mapwith the same guard.
Google ADK
from suvra.integrations.google_adk import suvra_before_tool_call
agent = LlmAgent(
...,
before_tool_callback=suvra_before_tool_call(suvra, fail_closed=True),
)
suvra_before_tool_call is an async ADK callback. It returns a dict (denial response) to short-circuit the tool call, or None to continue.
LlamaIndex
from suvra.integrations.llamaindex import guard_tools, SuvraToolWrapper
guarded = guard_tools(suvra, tools, fail_closed=True)
# or wrap a single tool:
guarded_tool = SuvraToolWrapper(suvra, tool, fail_closed=True)
Denied tool calls surface as a ToolOutput with an error payload, so the agent sees why the tool refused and can react.
OpenClaw
from suvra.integrations.openclaw import OpenClawGuard
guard = OpenClawGuard(suvra, default_actor="openclaw")
result = guard.execute("file.write", {"path": "out.txt", "content": "hello"})
OpenClawGuard.execute(action_type, params) wraps Suvra's execute flow with OpenClaw-specific actor defaults and action-id generation.
UiPath
from suvra.integrations.uipath import (
SuvraGovernedRuntime,
guard_process,
guard_activity,
suvra_guardrail_handler,
)
runtime = SuvraGovernedRuntime(suvra, inner_runtime, fail_closed=True)
@guard_process(suvra, action_type="uipath.process.run", fail_closed=True)
def run_payroll(...): ...
@guard_activity(suvra, action_type="uipath.activity.http", fail_closed=True)
def post_invoice(...): ...
handler = suvra_guardrail_handler(suvra, fail_closed=True)
SuvraGovernedRuntime(suvra, inner_runtime, *, fail_closed=False)— async runtime wrapper that validates every invocation against policy.guard_process/guard_activity— decorators for process-level and activity-level governance.suvra_guardrail_handler— escalation handler for UiPath guardrail events.
Generic decorator
If your framework isn't listed, use the framework-agnostic decorator:
from suvra.sdk.decorators import guarded_tool
@guarded_tool(suvra, action_type="http.request")
def fetch(url: str):
...
Or use the built-in shorthand on the client itself:
@suvra.tool("http.request")
def fetch(url: str):
...
Related
- Deployment — install the Control Plane and Enforcement Nodes
- Agents dashboard — full registration schema and validation rules