Navige Technical Reference
Navige is a governance proxy and API for AI agent tool calls. It sits between your agent and external actions, evaluating each call against your rules before allowing it to proceed. Every decision is logged to Supabase and anchored to the Polygon blockchain hourly.
https://api.navige.ai
x-api-key: tl_your_key
Quick Start
The fastest path is the drop-in proxy — change one environment variable and every OpenAI or Anthropic call is governed automatically.
Option A — OpenAI proxy (no code change)
from openai import OpenAI client = OpenAI( api_key="sk-your-openai-key", base_url="https://api.navige.ai/v1", # ← only change needed default_headers={"x-api-key": "tl_your_key"} # ← add TrustLoop auth ) # Everything else is identical to normal OpenAI usage
Option B — Python SDK (explicit intercept)
pip install trustloop-sdk
from trustloop import TrustLoop tl = TrustLoop(api_key="tl_your_key", agent_name="my-agent") # Option 1: explicit intercept result = tl.intercept("send_email", {"to": "user@example.com"}) if result["allowed"]: send_email(...) # Option 2: decorator — wraps a function, blocks it if not allowed @tl.guard() def delete_records(table: str, where: dict): ...
Authentication
All authenticated endpoints require your Navige API key. Pass it as a header:
x-api-key: tl_your_key_here
Keys are created when you sign up at navige.ai/signup. Each key belongs to a tenant and carries all associated limits and rules. Retrieve a lost key via POST /api/resend-key with your email.
OpenAI Drop-in Proxy
Endpoint: POST /v1/chat/completions Requires x-api-key
A transparent proxy to the OpenAI Chat Completions API. Set this as your client's base_url. Your OpenAI key goes in the standard Authorization: Bearer header. Navige API key goes in x-api-key.
base_url and default_headers to your client constructor.Headers
| Header | Required | Description |
|---|---|---|
| Authorization | Required | Your OpenAI key: Bearer sk-xxx |
| x-api-key | Required | Your Navige key: tl_xxx |
| x-agent-name | Optional | Agent identifier for per-agent tracking in the dashboard |
Python
from openai import OpenAI client = OpenAI( api_key="sk-your-openai-key", base_url="https://api.navige.ai/v1", default_headers={ "x-api-key": "tl_your_key", "x-agent-name": "finance-agent" # optional } )
Node.js
const { OpenAI } = require('openai') const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, baseURL: 'https://api.navige.ai/v1', defaultHeaders: { 'x-api-key': process.env.TRUSTLOOP_API_KEY, 'x-agent-name': 'my-agent' } })
Anthropic Drop-in Proxy
Endpoint: POST /proxy/anthropic/v1/messages Requires x-api-key
Transparent proxy to the Anthropic Messages API. Intercepts tool_use content blocks before returning the response to your agent. Same governance pipeline as the OpenAI proxy.
Headers
| Header | Required | Description |
|---|---|---|
| x-anthropic-api-key | Required | Your Anthropic API key |
| x-api-key | Required | Your Navige key |
| anthropic-version | Optional | Forwarded to Anthropic. Default: 2023-06-01 |
| x-agent-name | Optional | Agent identifier for dashboard tracking |
Python
import anthropic client = anthropic.Anthropic( api_key="sk-ant-your-key", base_url="https://api.navige.ai/proxy/anthropic", default_headers={ "x-api-key": "tl_your_key", "x-agent-name": "my-claude-agent" } )
Python SDK
pip install trustloop-sdk # sync (requests) pip install "trustloop-sdk[async]" # + async (httpx) pip install "trustloop-sdk[langchain]" # + LangChain helpers pip install "trustloop-sdk[crewai]" # + CrewAI helpers pip install "trustloop-sdk[all]" # everything
Core client
from trustloop import TrustLoop, TrustLoopBlockedError tl = TrustLoop(api_key="tl_xxx", agent_name="my-agent") # Explicit intercept result = tl.intercept("send_email", {"to": "...", "subject": "..."}) if result["allowed"]: send_email(...) # Guard decorator — raises TrustLoopBlockedError if blocked @tl.guard("delete_records") def delete_records(table: str, where: dict): ... # LangChain integration from trustloop.integrations.langchain import wrap_tools governed_tools = wrap_tools(tl, tools) # CrewAI integration from trustloop.integrations.crewai import governed_tool @governed_tool(tl) class SendEmailTool(BaseTool): ...
Node.js SDK
npm install trustloop
const { TrustLoop } = require('trustloop') const tl = new TrustLoop({ apiKey: process.env.TRUSTLOOP_API_KEY, agentName: 'my-agent' }) const result = await tl.intercept('send_email', { to: 'user@example.com' }) if (result.allowed) { await sendEmail(...) }
MCP — Claude Desktop
Connect Claude Desktop by adding Navige as an MCP server in your config. Every tool call Claude makes passes through Navige's governance pipeline.
{
"mcpServers": {
"trustloop": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://api.navige.ai/sse?api_key=tl_xxx"]
}
}
}
REST Intercept
Use the REST endpoint when you want explicit control — call it before any sensitive action in your own code, no SDK needed.
POST /api/intercept POST Auth
Evaluates a tool call against your governance rules. Call this before executing any sensitive action. Optionally, include forward_to to have Navige execute the tool on your behalf after approval — single round trip, actual response returned.
Request body
| Field | Type | Required | Description |
|---|---|---|---|
| tool_name | string | Required | The action or tool being called. Use descriptive names: send_email, delete_record, transfer_funds. |
| arguments | object | Optional | Parameters passed to the tool. Included in AI rule evaluation and audit log (PII masked before storage). |
| agent_name | string | Optional | Identifier for the calling agent. Enables per-agent tracking, breakdowns, and scoped kill-switches. |
| reason | string | Optional | Plain English explanation of why the agent wants to take this action. Stored in the audit log and shown in the approval email so the human approver sees intent, not just raw parameters. PII is masked before storage. |
| forward_to | object | Optional | If provided and the call is ALLOWED, Navige forwards the request to this HTTP endpoint and returns the real response. If the tool has a stored credential, it is injected automatically. Blocked calls are never forwarded. See below. |
| approval_id | string | Optional | UUID from a previous PENDING response. Pass with approved_hash to fast-path the call after human approval without re-evaluating rules. |
| approved_hash | string | Optional | The payload_hash returned in the PENDING response. Navige verifies this matches the stored hash and the current arguments — if args changed since approval, the call is blocked. |
forward_to object
| Field | Type | Required | Description |
|---|---|---|---|
| url | string | Required | The HTTPS endpoint to call. Private/internal IPs are blocked. |
| method | string | Optional | HTTP method. Defaults to POST. |
| headers | object | Optional | Headers to include in the forwarded request (e.g. Authorization). Not stored in audit logs. |
| body | object | Optional | Request body to forward. If omitted, arguments is used as the body. |
result = requests.post("https://api.navige.ai/api/intercept", headers={"x-api-key": "tl_xxx"}, json={ "tool_name": "send_email", "arguments": {"to": "user@example.com", "subject": "Hello"}, "agent_name": "my-agent", "reason": "User requested a welcome email after completing onboarding", "forward_to": { "url": "https://api.resend.com/emails", "method": "POST", "headers": {"Authorization": "Bearer re_xxx"} } } ).json() # result → { "allowed": true, "forwarded": true, "status_code": 200, "result": {...} } # If blocked → { "allowed": false, "decision": "BLOCKED" } — forward_to is never called
Response
{ "allowed": true, "decision": "ALLOWED" }
{ "allowed": true, "decision": "ALLOWED", "forwarded": true, "status_code": 200, "result": { "..." } }
{ "allowed": false, "decision": "BLOCKED", "message": "Blocked by governance rule: ..." }
{ "allowed": false, "decision": "ESCALATED", "status": "pending_approval", "approval_id": "uuid", "payload_hash": "sha256hex", "expires_at": "2026-07-22T14:30:00.000Z" }
After the human approves, retry with approval_id and approved_hash (the value of payload_hash above). Navige verifies the approval and that the payload hasn't changed before allowing.
GET /api/logs GET Auth
Returns the last 100 tool call records for your account, newest first.
Query params
| Param | Description |
|---|---|
| agent | Filter by agent name. Use all or omit for all agents. |
| limit | Max results. Default 100. |
GET /api/stats GET Auth
Returns aggregate counts for the current month plus per-agent breakdown.
{
"total": 1842,
"allowed": 1790,
"blocked": 48,
"pending": 4,
"usage": { "plan": "growth", "used": 1842, "limit": 1000000 },
"agents": {
"used": 3, "limit": 10,
"breakdown": [
{ "name": "finance-agent", "total": 920, "allowed": 898, "blocked": 22 }
]
}
}
Approval Rules Auth
| Field | Required | Description |
|---|---|---|
| rule_text | Required | Plain-English rule: "Block any action that deletes customer data" |
| action | Required | block or approve (requires human approval) |
| approver_email | Optional | Override notification email for this rule. Falls back to account default. |
Kill-Switch Auth
agent_name: null for global blocks.| Field | Required | Description |
|---|---|---|
| tool_name | Required | Tool to block |
| reason | Optional | Reason stored in audit log |
| agent_name | Optional | Scope block to a specific agent. Omit or null for all agents. |
Tool Registry Auth
Register your real tools so Navige's MCP server advertises them to Claude Desktop instead of the default demo set. Each tool can include a forward_url — when a call is ALLOWED, Navige calls that endpoint and returns the real response.
upsert behaviour — posting the same tool_name twice updates it.| Field | Required | Description |
|---|---|---|
| tool_name | Required | Unique name for this tool, e.g. send_email |
| description | Required | Plain-English description shown to the LLM |
| input_schema | Optional | JSON Schema object describing the tool's arguments |
| forward_url | Optional | HTTPS endpoint to call when this tool is ALLOWED. If omitted, Navige logs the call but does not execute it. |
| forward_method | Optional | HTTP method for the forwarded call. Default POST. |
| forward_headers | Optional | Headers for the forwarded request, e.g. {"Authorization": "Bearer sk_xxx"}. Not stored in audit logs. |
requests.post("https://api.navige.ai/api/tools", headers={"x-api-key": "tl_xxx"}, json={ "tool_name": "send_email", "description": "Send a transactional email", "input_schema": { "type": "object", "properties": { "to": {"type": "string"}, "subject": {"type": "string"}, "body": {"type": "string"} }, "required": ["to", "subject", "body"] }, "forward_url": "https://api.resend.com/emails", "forward_headers": {"Authorization": "Bearer re_xxx"} } )
Credential Storage
Store an encrypted API key for a tool. Navige injects it automatically into forward_to requests — the agent never holds the credential directly. Credentials are encrypted with AES-256-GCM at rest and never returned by the API.
| Field | Required | Description |
|---|---|---|
| header_name | Optional | Header to inject the credential into. Default Authorization. |
| value | Required | The credential value, e.g. Bearer sk-xxx. Encrypted immediately, never stored in plain text. |
{ exists, header_name, created_at } — the credential value is never returned.Pending Approvals Auth
| Field | Required | Description |
|---|---|---|
| action | Required | "approved" or "denied" |
Governance Pipeline
Every call to /api/intercept or through the proxy runs this pipeline in order. The first rule that matches stops evaluation and returns a decision.
agent_name is new this month, checks whether the tenant has capacity for another agent under their plan.AI Rule Caching
To keep latency low, Navige uses two caches:
- Rules cache — governance rules per account, refreshed regularly. Invalidated immediately when you create or delete a rule.
- Decision cache — AI evaluation result per unique tool call pattern, short TTL. Invalidated when rules change. In practice this achieves ~90%+ cache hit rate for agents with consistent calling patterns.
PII & Compliance
Before any tool call is written to the audit log, Navige's compliance middleware automatically:
- Masks PII — emails, phone numbers, card numbers, names, national IDs replaced with
[PII MASKED] - Redacts secrets — API keys, passwords, tokens, bearer credentials replaced with
[REDACTED] - Scores risk — each tool call assigned LOW / MEDIUM / HIGH risk based on tool name and argument patterns
Additional compliance endpoints:
GET /api/compliance/stats— PII masked count, secrets redacted count, risk breakdownGET /api/compliance/dsar— Full GDPR Art. 15 / CCPA data subject access request export (JSON)DELETE /api/logs/purge?days=N— Delete logs older than N days (data retention)
Blockchain Anchoring
Every hour, Navige hashes all tool call logs from the previous hour and records the hash on the Polygon Mainnet via a smart contract at 0xd2544fc3164ac0eBfb6B7A2c193800F9651Fc46F.
This creates an independently verifiable tamper-evident record. If any logs are deleted or modified in Supabase, recomputing the hash from the remaining records will not match what's on-chain.
Anchor records are stored alongside your audit logs. Use the Blockchain tab in your dashboard to see every anchor with a direct Polygonscan link, or query the API below to verify programmatically.
GET /api/blockchain/anchors GET Auth
Returns the list of blockchain anchor records for your account. Each record includes the batch hash, Polygon transaction hash, and a pre-computed Polygonscan link so you can verify without any blockchain tooling.
Query params
| Field | Type | Required | Description |
|---|---|---|---|
| limit | number | Optional | Max records to return. Default 20, max 100. |
{
"contract_address": "0xd2544fc3164ac0eBfb6B7A2c193800F9651Fc46F",
"anchors": [
{
"id": "uuid",
"log_hash": "0xabc123...",
"tx_hash": "0xdef456...",
"log_count": 142,
"created_at": "2026-07-22T14:00:00.000Z",
"polygonscan_url": "https://polygonscan.com/tx/0xdef456..."
}
]
}
How to verify a batch independently
- Export your audit log for the batch's time window
- Recompute:
ethers.keccak256(ethers.toUtf8Bytes(JSON.stringify(records)))overid, tenant_id, tool_name, status, created_atordered bycreated_atascending - Compare to
log_hashabove - Open the
polygonscan_url→ More details → Input data — the same hash is written on-chain
Plan Limits
| Plan | Price | Calls/mo | Agents | Retention |
|---|---|---|---|---|
| Free | $0 | 5,000 | 1 | 7 days |
| Starter | $29/mo | 100,000 | 3 | 30 days |
| Growth | $249/mo | 1,000,000 | 10 | 90 days |
| Business | $649/mo | 5,000,000 | Unlimited | 1 year |
| Enterprise | Custom | Custom | Unlimited | Custom |
Limits are enforced at the intercept point. When a limit is exceeded, the API returns HTTP 429 with a clear error message. Usage resets on the 1st of each calendar month.