Every tool that talks to an outside service needs a credential: the token, OAuth refresh, or API key that proves who's asking. Chatzuri stores credentials encrypted, decrypts them only at call time, and never shows the raw values to the agent.
Where credentials live
Credentials are stored on the team, not the agent. One Slack credential can back the Slack channel (incoming messages) and the Slack tool (outgoing actions) for every agent in the team. You manage them at Team settings → Credentials.
Adding a credential
- Open Team settings → Credentials and click + New credential.
- Pick the provider (e.g. Stripe, GitHub, PostgreSQL). Each one has its own form — Stripe asks for a secret key, Postgres asks for a connection string, Google Drive asks for OAuth client id + refresh token, and so on.
- Give the credential a memorable name (e.g.
stripe-live,support-zendesk). - Click Test. Chatzuri calls the real provider with your input and reports back: connected, scope warnings, or what was rejected.
- Click Save. The secret fields are encrypted at rest with AES-256-GCM and only decrypted when a tool needs them.
Bind a credential to a tool
Open an agent → Tools & Actions → pick a tool → choose a credential from the picker. The agent now uses that credential whenever it calls the tool. Different agents in the same team can use the same credential or different ones.
The capability profile
Most tool credentials carry an allowedOperations setting with three values:
- Read-only (default for new credentials) — lookups, searches, listings, downloads. Cannot create, update, or delete.
- Read + Write — adds creates and updates. Still cannot delete.
- Full access — adds deletes (and other destructive ops like Vercel env-var deletes or PR merges).
The profile is enforced server-side before the call reaches the provider. A jailbroken prompt or a confused model can't do more than the profile permits, even if the underlying token has wider scope.
repo:read for a read-only credential — that way two locks have to fail for anything bad to happen.Hard caps you cannot override
Some limits are enforced server-side regardless of what the model asks for or what the credential allows:
- 500 rows max per list / query response.
- 256 KB max serialized response size — extra rows are truncated and the response is marked
truncated: true. - 30 s max per-request timeout for outbound calls.
- 100 MB upload / download cap on cloud-storage tools.
- 5 MB inline-content cap on file downloads (text MIME types only — bigger files come back as a signed URL).
- 7 days max signed-URL TTL.
- 10 s custom action timeout.
The two tests every tool ships with
- Credential test — calls a free, read-only endpoint on the provider (Stripe
/v1/balance, GitHub/user, PostgresSELECT 1, etc.). Reports back the account name, region, scope, or rejection reason. - Tool test — runs the tool itself against the credential with a hard-coded read-only input. For Stripe that's the same
/v1/balance; for AWS S3 it'slist_objects limit=1; for GitHub it'sget_repo.
Rotating a credential
- Generate the new key in the upstream provider.
- Open the credential in Chatzuri, paste the new value, click Save.
- Revoke the old key at the provider.
Every tool that uses the credential picks up the new value on its next call — no restart, no agent edit.
Why credentials are team-scoped
Channels (incoming Slack / WhatsApp / Telegram messages) and tools (outgoing Slack chat.postMessage, WhatsApp send_text, etc.) for the same provider share a single credential. That means one Stripe key works for the Stripe payment tool across every agent in the team; one Postgres credential gives every agent the same database connection. No duplication, one place to rotate.
