Documentation
Cartha sits between your agent and the model. Change a base URL, and every call is checked against your rules, limited by your budgets, held for approval when it should be, and recorded.
1. Quick start
Sign in, create a key on the Keys page, then open the Gateway page for a snippet with your details. For an OpenAI app it is two changes:
from openai import OpenAI
client = OpenAI(
base_url="https://cartha.in/api/v1/proxy/v1", # was https://api.openai.com/v1
api_key="<your Cartha key>", # store provider keys on Gateway
default_headers={"X-Cartha-Agent": "support-bot"},
)
# chat, responses, and embeddings all use this base URL
client.chat.completions.create(model="gpt-4o-mini", messages=[...])
client.embeddings.create(model="text-embedding-3-small", input="...")X-Cartha-Agent names the agent in the dashboard. An agent key tied to one agent sets it for you. Make one call, then open Gateway or Traces to see it. Prefer this universal base for any framework; provider-specific paths still work.
2. Providers
Every route is under https://cartha.in/api/v1/proxy. Your provider credential goes where the provider expects it.
| Provider | Path | Provider key | Cartha key |
|---|---|---|---|
| Universal (any framework) | /v1 — chat/completions, responses, embeddings; model picks provider | Authorization: Bearer <Cartha key> (store provider keys), or provider key | api_key, or X-Api-Key |
| OpenAI (chat) | /openai/v1/chat/completions | Authorization: Bearer <OpenAI key> | X-Api-Key |
| OpenAI (Responses) | /openai/v1/responses | Authorization: Bearer <OpenAI key> | X-Api-Key |
| OpenAI (embeddings) | /openai/v1/embeddings | Authorization: Bearer <OpenAI key> | X-Api-Key |
| Azure OpenAI | /azure/openai/deployments/<deployment>/chat/completions|embeddings | api-key | X-Api-Key, plus X-Cartha-Azure-Resource |
| Anthropic | /anthropic/v1/messages | x-api-key | X-Cartha-Key |
| Gemini | /gemini/v1beta/models/<model>:generateContent | x-goog-api-key | X-Api-Key |
| Vertex AI | /vertex/v1/projects/<project>/locations/<location>/publishers/google/models/<model>:generateContent | Authorization: Bearer <token> | X-Api-Key |
| Azure OpenAI (v1) | /azure/openai/v1/chat/completions|responses|embeddings | api-key | X-Api-Key, plus X-Cartha-Azure-Resource |
| Custom (OpenAI-compatible) | /custom/<name>/v1/chat/completions|responses|embeddings | stored with Cartha | Authorization: Bearer <Cartha key> |
| Sandbox (sample model) | /sandbox/v1/chat/completions | none | Authorization: Bearer <Cartha key> |
| AWS Bedrock | /bedrock/model/<model id>/converse | Authorization: Bearer <Bedrock API key> | X-Api-Key, plus X-Cartha-Bedrock-Region |
Anthropic already uses x-api-key for its own key, so there the Cartha key travels in X-Cartha-Key. Bedrock works with Bedrock API keys only: AWS-signed requests cannot pass through any proxy.
3. Rules
Write a rule in plain language or as exact checks on a field. A rule can block, hold for a human, only record what it would have blocked, or alert Slack. Rules apply to what the user typed, to each tool call the model asks for (including its arguments), and, if you choose, to the model's reply.
{"name": "Only email our own domain", "action": "block",
"checks": [{"type": "domain_allowlist", "field": "to", "domains": ["contoso.com"],
"tool_names": ["send_email"]}]}
{"name": "No SSNs in replies", "action": "block",
"checks": [{"type": "regex_block", "field": "content", "pattern": "\\b\\d{3}-\\d{2}-\\d{4}\\b",
"action_types": ["model_output"]}]}- Check types: domain allow/block list, amount limit, regex, keyword, tool block.
- Start with
audit_log: it never blocks and records every call, flagging what it would have blocked. - A blocked call is refused with a 403 and a clear reason; the model's blocked tool call is never returned to your app.
4. Human approval
A rule whose action is require_human_approval refuses the call and opens a request in Escalations. When a person approves it, your app retries the identical request and it goes through, once.
- An approval covers one agent, one rule and the exact content. Change anything and it needs a new approval.
- It is single use, and every other rule still applies to the approved request.
- The retry is your app's job; nothing is held open on Cartha's side.
5. Budgets and limits
- Budgets: create an envelope with an amount and an optional tool allow-list, then send
X-Cartha-Budget: <id>. Calls are refused once it is used up. A budget can be passed by at most one call, because a call's cost is only known afterwards. - Runaway loops: rules can use
autonomous_steps, the number of tool-call rounds since a person last spoke, to cap how long an agent runs unattended. - Kill switch: pause one agent from its page; its calls are refused immediately.
- Failover: name a second provider with the same API and Cartha retries there once if the first is down.
6. Privacy and storage
On the Gateway page you set, once for the organisation, whether personal data is masked before it reaches the provider, and whether prompts and replies are kept in traces. Rules still judge the real text. A request header can ask for stricter handling but can never loosen what the organisation or the server sets.
X-Cartha-Redact-PII: true # mask emails, phone and card/ID numbers before sending X-Cartha-Store-Content: false # keep no prompt or reply text, only metadata and cost
7. No-code platforms (HTTP)
Copilot Studio and Custom GPTs cannot route their model calls through the gateway. They can call an HTTP action. Cartha publishes an OpenAPI file for it, covering the policy check (with human approval and a batch form) and budgets.
POST https://cartha.in/api/v1/policies/evaluate
X-Api-Key: <your Cartha key>
{"agent_id": "support-bot", "action_type": "tool_call",
"action_data": {"tool_name": "send_email", "to": "x@gmail.com"}}
-> {"allowed": false, "policy_name": "...", "reason": "...", "action": "block"}This is a check the agent chooses to make. A confused or injected agent can skip it, so treat it as guidance plus an audit trail, not a guarantee.
8. Reading the log
Every call is a trace. Where to look:
- Gateway: the last 24 hours at a glance: calls, blocks, spend and the latest calls with the reason.
- Traces: one call in detail: model, tokens, cost, tool calls, which rule fired. Replay shows what a new rule would have stopped.
- Escalations: calls waiting for a person.
- Costs: spend per agent.
- Every response carries
x-cartha-trace-idso you can find its trace.
9. What it cannot do
- It governs traffic that passes through it. A client that calls the provider directly is not covered unless your network forbids that.
- It cannot see what your own code does after the model answers, such as a hardcoded API call.
- Hosted tools the provider runs itself (web search, code execution) can be allowed or refused in the request, but not stopped after the fact.
- A streamed request with a rule on the reply text, a budget or a failover provider is buffered, so it arrives after the model finishes.
10. FAQ
Do I have to install anything?▼
No. Point any OpenAI-compatible client at /api/v1/proxy/v1 and use your Cartha key (store provider keys on the Gateway page), or keep the provider key and send Cartha in X-Api-Key.
What does the gateway see?▼
What passes through the model call: what the user typed, what the model asks your app to do (tool calls, with their arguments), and what the model writes back. It does not see what your own code does afterwards.
What if my app does something outside a model call?▼
Call the policy check over HTTP before the action (section 7). It is a check your code chooses to make, not enforcement.
What if Cartha is down?▼
By default the gateway fails closed: if it cannot evaluate your rules, the request is refused rather than sent unchecked. A deployment can choose to fail open instead.
Does streaming work?▼
Yes. Text is streamed to your client as it arrives. When the model starts a tool call, Cartha holds that part until the call has been checked, so a blocked tool call is never sent to your app. Requests with a rule on the reply text, a budget or a failover provider are buffered instead, because those checks need the whole answer first.
Is my prompt stored?▼
By default a PII-scrubbed copy is kept on the trace. You can switch that off for the organisation on the Gateway page, or per request. Then only model, cost, tool names and the rule outcome are kept.