Developer documentation
Credential broker
Last reviewed 31 August 2026
All docs
Your agents need to call GitHub, Stripe, your CRM or an internal API, but you do not want the API key inside the agent: in its prompt, its memory, its logs, or the hands of whoever injects instructions into it. With the broker, the key lives in CAIN. The agent asks CAIN to make the call, and CAIN decides first.
Store a credential (owner or admin key)#
curl -s https://cainstudio.online/fabric/broker/credentials -H "X-API-Key: $CAIN_API_KEY" \
-H 'content-type: application/json' \
-d '{"name":"github", "kind":"bearer", "secret":"ghp_...",
"allowed_hosts":["api.github.com"], "allowed_methods":["GET","POST"]}'
kind is bearer, header (with header_name, for example X-API-Key), basic (user:password) or query (with header_name as the parameter name). Hosts can be exact or *.example.com. The secret is encrypted at rest and no endpoint ever returns it. Agent keys can use credentials but cannot store, change or revoke them.
Call through CAIN (any workspace key, including agent keys)#
curl -s https://cainstudio.online/fabric/broker/call -H "X-API-Key: $AGENT_KEY" \
-H 'content-type: application/json' \
-d '{"credential":"github", "method":"POST", "url":"https://api.github.com/repos/acme/app/issues",
"json":{"title":"Flaky test"}, "agent_id":"triage-bot"}'
1. The URL and method must be inside the credential's scope. Otherwise the answer is 403, and no decision is made and no request is sent. 2. CAIN decides on the call as the tool http_<method> (here http_post), with the credential name, URL and body as arguments. Your tool rules, the risk model, the agent's trust and approvals all apply. The decision is recorded like any other. 3. Allowed means CAIN sends the request with the credential added and returns {"executed": true, "response": {"status", "headers", "body"}}. Held returns 202 with an approval_id; ask again after a person approves. Refused returns 403, and nothing is sent.
From Python (cainstudio 0.3.0 and later):
resp = cain.broker_call("github", "https://api.github.com/repos/acme/app/issues", method="POST",
json_body={"title": "Flaky test"}, wait_for_approval=120)
What protects the key#
- It is only ever sent to the credential's own hosts and methods. Redirects are not followed, so a
302
cannot carry it elsewhere.
- Requests go only to public addresses (the same checks as webhooks), and the connection is made to the
address that was checked.
- An
Authorizationheader the agent supplies is dropped. If the upstream echoes the key back, it is
replaced with [REDACTED:brokered-credential] before the response reaches the agent.
- Revoking (
DELETE /fabric/broker/credentials/<name>) takes effect on the next call.
Limits#
- The stored credential is long-lived. CAIN does not mint short-lived per-call tokens with each provider
(OAuth token exchange).
- Responses are capped at 1 MB, and each call times out after 20 seconds.