Popular starting points. Use Tab or arrow keys to browse results.

Skip to content
Aten SecurityThoth docs

Instrument your own agent

Put real tool callbacks behind Thoth's policy check and preserve actor context.

Complete Your first governed agent before connecting tools that read private data or change external systems.

1. Define the action and its owner

Choose a distinct agent ID and stable tool names. Start with one read-only tool. Agree with your administrator on the server policy for that action, the initiating identity, and which actions need human approval.

approved_scope describes the intended tool set; adding a name to it does not create server policy. Use your tenant's supplied endpoint and a runtime execute key. Keep administrative credentials out of the agent process.

2. Wrap the tool execution path

In the first-agent example, replace the demo.read callback with your own read-only function, change the agent ID, and set the agreed scope. Pass the initiating user's verified identity and a session ID for the request. Keep the mode and failure settings agreed for your deployment.

Choose the adapter that matches how your framework actually executes tools:

Your execution pathIntegration
Python agent exposing .toolsinstrument()
Python function map or custom model tool loopPython SDK: instrument the toolchain, then dispatch through its governed function map
LangGraph graph, tools, or ToolNodeLangGraph integration
TypeScript tool objects or model tool loopTypeScript SDK
Go function callbacksGo SDK: WrapTool or a session-scoped wrapper
External MCP server used by a desktop clientMCP proxy

Your model may choose a tool name and arguments. Your application must dispatch that choice through the governed wrapper. Do not retain an alternate route to the original callback. Reject unknown tool names before dispatch.

Python: dispatch a tool through a governed function map

This complete example uses a local document lookup to illustrate a custom agent loop. Ask your administrator to configure policy for the new agent ID and read_document tool first. Set THOTH_AGENT_ID to that agreed agent ID and APP_USER_ID to the identity established by your application. Reuse your runtime connection variables from the first-agent guide.

Save as my_agent.py in the project where you installed atensec-thoth:

my_agent.py
import os
from uuid import uuid4
from thoth import instrument_toolchain, toolchain_function_map, ThothPolicyViolation
 
 
def read_document(args: dict) -> str:
    documents = {"welcome": "Welcome to your governed agent"}
    return documents[args["document_id"]]
 
 
governed = instrument_toolchain(
    {"read_document": read_document},
    agent_id=os.environ["THOTH_AGENT_ID"],
    tenant_id=os.environ["THOTH_TENANT_ID"],
    api_url=os.environ["THOTH_API_URL"],
    api_key=os.environ["THOTH_API_KEY"],
    approved_scope=["read_document"],
    user_id=os.environ["APP_USER_ID"],
    session_id=str(uuid4()),
    enforcement="block",
)
functions = toolchain_function_map(governed)
 
# In a real loop, validate the model's proposed name and arguments here.
# The model never receives credentials or the original callback.
proposed_name = "read_document"
proposed_args = {"document_id": "welcome"}
if proposed_name not in functions:
    raise ValueError("Unknown tool")
try:
    print(functions[proposed_name](proposed_args))
except ThothPolicyViolation as refusal:
    print(f"Action refused: {refusal.reason}")

Run python my_agent.py. If policy permits the action, the output is Welcome to your governed agent. Otherwise inspect the refusal and server decision; do not retry read_document directly. Replace the local lookup with a real read-only callback after you verify policy. For a model-specific tool loop, use the corresponding Python SDK adapter; TypeScript and Go can reuse the wrapped tool execution pattern from the first-agent guide.

3. Handle decisions without bypassing them

  • ALLOW: execute the governed callback and return its result.
  • STEP_UP: let the supported SDK approval flow resolve; keep the action paused.
  • BLOCK: return a clear refusal or escalate through the approved workflow.
  • Service or authentication error: keep fail-open disabled and resolve the failure.

Do not catch an exception and invoke the raw callback as a fallback. Keep policy refusals separate from callback failures in your application's logs and user messages. Avoid exposing keys, hold tokens, or sensitive arguments in those messages.

4. Verify before adding more tools

Test a permitted call and a refused call against your configured policy. Confirm the refused callback never executed. Inspect the reason, agent, actor, session, and correlation identifiers in decision history. If approval is part of your policy, test approval, denial, and expiry before enabling sensitive actions.

Check telemetry delivery separately and verify any receipt or export you intend to use as evidence. Repeat verification when you change tools, policies, SDK releases, or identity handling.

Next, use your SDK reference for framework and lifecycle details, or configure supported governance settings as code.

On this page