Skip to content

FAQ

32 results

FAQ-001Platform

What problem does Caracal solve?

Caracal gives agents and automated workflows short-lived, policy-approved authority instead of long-lived credentials. The agent asks for scoped authority at the moment it acts, STS evaluates policy, Gateway or an adapter enforces the mandate, and Audit records the decision and result.

See Authority and Enforcement and the Caracal Mental Model.

Related: FAQ-002, FAQ-003, FAQ-016

FAQ-002Platform

Is Caracal an identity provider, secrets manager, or API gateway?

No. Caracal is an authority broker for agent and workload actions. It can sit in front of HTTP resources like a protected Gateway, and it can broker provider credentials, but it does not replace your IdP, your static config store, or your general API management layer.

Use an IdP for human login, a secret manager for static application configuration, and Caracal when an agent or service needs scoped, auditable authority for a resource.

Related: FAQ-001, FAQ-009, FAQ-013

FAQ-003Architecture

What should a zone represent?

A zone should represent a trust boundary: the set of resources, sessions, policies, signing keys, and audit records that are allowed to share authority state. Use a separate zone when two workloads need independent signing keys, policy activation, or audit trails. Use one zone with separate resources when the same trust boundary protects multiple upstreams.

For examples, see Model Your Application in Caracal.

Related: FAQ-004, FAQ-009, FAQ-011

FAQ-004Architecture

Does this repository implement managed multi-tenancy?

No. The open-source product gives you Zones as an isolation primitive. You can model customers, environments, or trust tiers with Zones and automate them through the Admin API. Managed tenant, team, SSO, and hosted lifecycle are not implemented in this repository.

To serve many of your own customers from one deployment without per-customer zones, see Serve Your Own Customers.

Evaluate any separate offering from its own current source, contract, and demonstrated behavior; this documentation cannot verify it.

Related: FAQ-003, FAQ-019

FAQ-005Identity

What is the difference between an application, Subject, Authority record, and Session?

An application is registered software that authenticates to Caracal. A Subject is the opaque JWT sub identity the work is attributed to - the application itself by default, or a Federated user supplied by a trusted identity provider. An Authority record is one STS exchange record. A Session is one governed Coordinator execution.

These identifiers are distinct: Authority record ID identifies one STS exchange, Root authority record ID identifies its exchange-chain root, and Session ID identifies one governed Coordinator execution.

Related: FAQ-006, FAQ-007, FAQ-008

FAQ-006Identity

Should I create one application per agent?

No. This is the most common modeling mistake, and it does not match how Caracal scales. An application and an agent are different layers:

  • An application is the credentialed security boundary. It is operator-provisioned (managed) or dynamically registered (DCR), holds a server-owned secret, and is the identity Caracal authenticates. Creating one is a deliberate, secret-bearing act.
  • An Session is the scalable runtime unit. The process that already holds the application credential creates Sessions at runtime - no secret, no registration, no Console step. One application backs many concurrent Sessions (up to 200 per application by default).

The default model is one managed application per durable service, with many Sessions under it. When that service fans out across sub-agents or jobs, each execution is a new Session under the same application. Policy and audit tell them apart by Session ID, lifecycle, labels, and Delegation chain.

Use a separate application only when an independently launched agent or workload needs an isolated, expiring credential and registry-visible identity. DCR supplies that boundary and binds exactly one Session.

See Identities and Applications and the Caracal Mental Model.

Related: FAQ-005, FAQ-007, FAQ-008

FAQ-007Identity

When should I use a managed application versus DCR?

Use a managed application for durable software you intentionally operate: a backend service, Gateway application, orchestrator, or agent runtime. Ordinary Session fan-out does not need DCR. Use DCR only when an independently launched identity needs an isolated, auto-expiring credential boundary, such as a per-tenant or per-integration process. DCR applications are registered through the Admin API, always expire, bind exactly one Session, and cannot parent further Sessions.

See Identities and Applications.

Related: FAQ-005, FAQ-006, FAQ-008

FAQ-008Identity

If many agents share one managed application, can policy and audit still tell them apart?

Yes, with one important distinction between attribution and credential isolation.

Each execution has a unique Session ID. Policy and audit record it with lifecycle, labels, parentage, and Delegation context. The web console Sessions view shows the same execution records.

Authority, not labels, is the security boundary. Labels are asserted by the credentialed workload and help policy and audit classify work; scopes, Delegations, and policy contain compromised workloads.

Filter the Admin API audit endpoint by session_id for one exact Session or by label for a role across many Sessions.

See Identities and Applications and Model Your Application in Caracal.

Related: FAQ-005, FAQ-006, FAQ-007

FAQ-009Resources

What is the difference between a resource and a provider?

A resource is the protected target and policy audience: the thing a mandate authorizes access to. A provider describes how Gateway authenticates upstream: no credential, Caracal mandate, OAuth, API key, or bearer token.

Keep target identity, scopes, and upstream URL on the resource. Keep secrets, token endpoints, OAuth settings, API keys, and bearer tokens on the provider.

Related: FAQ-010, FAQ-011, FAQ-013

FAQ-010Resources

Why must the resource identifier stay stable if the upstream URL can change?

Policies, grants, mandates, and audit records refer to the resource identifier. If you use a mutable deployment hostname as the identifier, changing infrastructure also changes your authority boundary and breaks audit continuity. Use a stable audience URI such as resource://pipernet, then change the upstream URL when routing changes.

Related: FAQ-003, FAQ-009, FAQ-011

FAQ-011Resources

How should I design scopes?

Use small action-oriented scopes such as pipernet:read, piperchat:comment, or mcp:tool:call. Do not encode environment, tenant, user, or hostname into scope names when that data belongs in the zone, principal, resource, or policy input.

Scopes answer “what action is allowed?” Resource identifiers answer “what target is protected?”

Related: FAQ-003, FAQ-009, FAQ-012

FAQ-012Resources

Do I manage grants directly?

In the current web-console flow, you usually define Resources, scopes, Applications, Subjects, and Policy rather than managing Grants as a separate daily object. Policy data can declare role-to-scope grants, while managed delegated Grants are lifecycle and revocation records. The active Policy set still makes the final allow, deny, or Approval decision.

If access is denied, inspect the active policy, Subject, application, resource, and scopes through request trace.

Related: FAQ-011, FAQ-016

FAQ-013Security

Is an application secret the same as a provider credential?

No. An application secret authenticates the application to Caracal. A provider credential authenticates Gateway or STS to an upstream provider such as Google, Slack, OpenAI, or an internal API. Agents should authenticate to Caracal and receive short-lived mandates; they should not receive long-lived provider credentials.

See Define Resources and Providers.

Related: FAQ-002, FAQ-009, FAQ-014

FAQ-014Security

When should I use per-user OAuth instead of a shared provider credential?

Use a connected upstream account (oauth2_authorization_code) when the upstream call must act as a specific consented account: a human completes the provider’s consent screen once for the shared account, or once per Subject when the connection is bound to a specific customer (typically a Federated user). Use a shared service credential (oauth2_client_credentials, api_key, or bearer_token) when the agent acts as the application with one operator-configured credential.

The concrete setup fields are in Provider Recipes.

Related: FAQ-013, FAQ-016

FAQ-015Runtime

Why are zone and policy commands in the web console instead of the caracal CLI?

The top-level caracal CLI is intentionally limited to local runtime lifecycle, process execution, upgrades, Console sign-in admission, and web console launch: up, down, status, upgrade, purge, allowlist, run, and web. Product-management workflows such as zones, applications, providers, resources, policies, audit, diagnostics, agents, and delegation live in the web console, Control API, and Admin SDK so they use one management surface and do not drift into duplicated CLI commands.

See Choose the Right Surface.

Related: FAQ-017, FAQ-018

FAQ-016Operations

What is the difference between a 403 from STS and a 403 from Gateway?

A 403 from STS means the exchange was authenticated but Policy did not allow the requested Resource scopes, or an Approval, Grant, or Session condition blocked issuance. A 403 from Gateway or a verifier means the request reached a protected boundary but the Mandate, Resource binding, scope check, revocation state, or route safety check failed.

Use request trace with the request ID to identify the surface before changing policy or resource configuration.

Related: FAQ-011, FAQ-012, FAQ-017

FAQ-017Operations

Where is the diagnostic bundle or doctor command?

The diagnostic bundle is exposed through existing surfaces instead of a separate top-level command. Use caracal status —json for runtime status, web console Diagnostics for Doctor checks (health, readiness, zones, preflight), audit for recent decisions, and request trace for a known request ID.

See Troubleshoot by Symptom and Inspect Diagnostics and Audit.

Related: FAQ-015, FAQ-016, FAQ-018

FAQ-018Operations

Why is an audit event missing?

First confirm the request reached a Caracal-protected boundary. If it did, check the selected zone, time window, request ID, Audit service readiness, Redis stream health, replay backlog, and DLQ. If the request failed before STS, Gateway, Coordinator, or an adapter emitted evidence, there may be no action-result event for that boundary.

Start with Inspect Diagnostics and Audit and Debug Infrastructure Issues.

Related: FAQ-016, FAQ-017

FAQ-019Scope

What does this documentation verify?

This documentation verifies only behavior implemented by the self-hosted open-source product and supported deployment assets in this repository. It does not establish managed hosting, SSO, SCIM, organization RBAC, commercial support, an SLA, certification, or regulatory conformity.

Use Review OSS Adoption Readiness to separate repository evidence from deployment and organizational responsibilities.

Related: FAQ-004

FAQ-020Identity

Two agents share the same application and labels - how do I tell which one acted?

Every governed execution has one canonical Session ID. It is returned when session() or startSession() starts the Session and is stamped onto its token exchanges and audit events.

Identical Sessions are interchangeable on purpose. A hundred [“pricing-worker”] Sessions fanned out under one application are meant to be fungible - that is how fan-out works, and it is why labels are a descriptor rather than a unique name. When you need to tell Sessions apart by meaning rather than by raw id, give them distinguishing labels, attach business correlation in metadata, or propagate a trace_id through the work.

To investigate, the zone audit endpoint filters directly on these fields: query session_id to follow one exact Session end to end, or label to scope to a role across a whole fleet of Sessions. The web console audit view exposes both filters.

To see Sessions that have ended, the Admin API exposes GET /v1/zones/{zone}/sessions. It supports status, lifecycle, label, parent Session, and application filters plus CSV export.

Related: FAQ-006, FAQ-008, FAQ-021

FAQ-021Security

A started Session uses application policy and narrowed authority - which wins?

Both apply, and they compose as a strict intersection - a logical AND - so the narrower of the two always wins. They are two independent layers with different jobs: a grant (the Delegation a narrowing session(grant=…) creates) caps which scopes the token may carry at all, while policy decides whether the action is allowed. Neither layer can ever add authority; each one can only subtract.

At token exchange a resource is released only if it passes every gate: the requested scopes must be within the resource’s own scopes, within the grant edge’s scopes (which is itself re-validated to be within the parent’s authority), the resource must fall inside the delegation, and policy must return allow. The effective authority is therefore policy ∩ grant ∩ resource ∩ delegation. This holds in both directions: if policy is the narrower of the two, policy wins and the grant cannot widen past it; if the grant is the narrower, the grant wins, because the token cannot request scopes outside the grant and resources outside the delegation are rejected even when policy would have allowed them.

There is no clash. A plain session() under a top-level parent runs at the application’s policy-bounded authority. Under a narrowed parent, Coordinator mirrors the parent’s Delegation onto the child. Use session(authority=Authority.narrow([…])) when the child should hold less. Every layer is subtractive.

See Delegation and Policy.

Related: FAQ-006, FAQ-008, FAQ-011

FAQ-022Identity

If child Sessions use the parent’s application, when is DCR used?

A DCR application is used by authenticating as it, not by starting it as a child. Because session() uses the caller’s application, a DCR application bound to exactly one Session cannot parent another Session.

The credential boundary between durable managed identities and short-lived DCR identities is named by registration_method (managed vs DCR), not by an agent’s lifecycle. A Session’s lifecycle is either task (the default) or service (heartbeat-leased), and a DCR application cannot host a service Session, so its one Session is always a task Session. A short-lived worker is therefore not a separate lifecycle - it is an ordinary task Session with a TTL (see FAQ-023).

The Admin API registers the DCR application and returns a one-time client secret and short expiry. An orchestrator injects those credentials into an independently launched workload, which authenticates with client_credentials and starts its single Session. STS creates Authority records as that workload exchanges.

The credential split is deliberate: minting a new credentialed identity is a privileged control-plane action, so a runtime cannot register applications for itself. The SDK consumes a DCR application by being configured with its credentials; only an operator or orchestrator with Admin API access mints one.

Because a DCR root has no parent and no Delegation, its authority is decided entirely by policy, not by inheritance - and policy is default-deny, so a DCR identity opens no tools until a policy grants it scopes. Policies receive input.principal.registration_method, so you write one policy class targeting registration_method == “dcr” (optionally narrowed by labels, resource, or zone) that covers every DCR application; you do not author a policy per DCR app. Pair that with per-tenant or per-job resources to keep each DCR identity scoped to its own data.

DCR provides a credential-isolated, independently revocable, auto-expiring, registry-visible identity for a per-tenant, per-job, or per-integration workload. It does not add execution attribution; Session ID already provides that.

See Identities and Applications and FAQ-007.

Related: FAQ-006, FAQ-007, FAQ-008

FAQ-023Identity

How do I model an orchestrator, managers, and short-lived workers?

Model the runtime under one managed application. Every execution is a Session. A short-lived worker is a task Session; least privilege is expressed with narrowed authority, and ttl_seconds adds an optional wall-clock cap.

  • The orchestrator uses a long-lived Session from startSession() when it needs a heartbeat lease.
  • Each manager is a plain session() that inherits the application’s authority.
  • Each task worker is session(authority=Authority.narrow([…])) - bounded to a subset of authority and auto-terminated when its block exits - with ttl_seconds=… added only when you also want a wall-clock cap.

A Session’s authority comes from its application, bounded by policy. A parent matters when authority is narrowed: Authority.narrow([…]) creates a Delegation that the server validates as a subset of the parent’s effective authority. Cross-application authority uses delegate(to=peer); the receiver consents by presenting the opaque, target-bound Delegation ID.

See Identities and Applications, Delegation, and FAQ-022.

Related: FAQ-006, FAQ-008, FAQ-022

FAQ-024Security

If A narrows authority to B and B starts C, does C stay bounded?

Yes. inherit carries the parent’s effective authority forward, so least privilege is transitive down a same-application Session tree. Suppose A starts B with Authority.narrow([pipernet:read]), then B starts C:

  • With inherit, Coordinator mirrors B’s Delegation onto C. C stays within B’s scopes, resource, constraints, and expiry.
  • With further narrowing, Coordinator rejects C unless C ⊆ B.
  • If B has no inbound Delegation, C runs under the application’s authority bounded by policy.

Cross-application authority is never inherited automatically; it requires delegate(to=peer), followed by receiver presentation of the opaque, target-bound Delegation ID. Application plus policy remains the hard boundary.

See Delegation and FAQ-023.

Related: FAQ-021, FAQ-023, FAQ-008

FAQ-025Identity

What is the difference between a task and a service lifecycle - and how do I model a task-and-die worker versus a time-limited one?

Every runtime actor is an Session; lifecycle only describes how it runs. There are two lifecycles, and they map directly onto the two SDK primitives:

  • Task - created with session(), recorded as lifecycle = “task”. It lives for the duration of its task: when its block exits it is terminated automatically. This single behavior covers both of the cases you are distinguishing. A “do one task and die” worker (for example a search sub-agent) is just session() whose block returns when the task is done. A “live up to N seconds then expire” worker is the same session() with ttl_seconds=N, which adds a hard wall-clock cap enforced by the TTL sweeper. The difference between “task-and-die” and “time-limited” is whether you set a TTL, not a different lifecycle.
  • Service - created with startSession(), start_session(), or StartSession() and recorded as lifecycle = “service”. This long-lived Session is governed by a renewable heartbeat lease rather than the task TTL sweeper.

The stored lifecycle column carries exactly these two protocol values. Use a long-lived Session when work must outlive one task; otherwise use session() with an optional TTL.

See Identities and Applications and FAQ-023.

Related: FAQ-022, FAQ-023, FAQ-007

FAQ-026Identity

Can two DCR applications have different policies, and can a DCR Session start children?

Different policies per DCR app: yes. Policy evaluation receives the full principal, including the specific input.principal.id (the application id), input.principal.labels, and input.principal.registration_method. Matching on registration_method == “dcr” is just the convenient way to write one rule that covers every DCR app; when two DCR apps need different authority, target their distinct application ids or labels, or scope them to different resources. There is no requirement that all DCR apps share a policy.

Can a DCR application start child Sessions: no. It binds exactly one Session; a second start is rejected with the protocol error dcr_application_already_bound.

Which Sessions can be parents: Sessions under managed applications can start child Sessions. A task parent cannot start a service child; the protocol reports task_session_cannot_start_service. DCR Sessions are isolated leaves, reported by the protocol as dcr_application_cannot_start_child and dcr_application_cannot_be_child.

See Identities and Applications and FAQ-022.

Related: FAQ-022, FAQ-025, FAQ-007

FAQ-027Runtime

Where does Caracal read caracal.toml from?

SDK loaders read exactly the path in CARACAL_CONFIG. If that variable is unset, they use SDK environment variables. They do not search the current directory, home directory, or OS Caracal config directory for caracal.toml. caracal run does not use an SDK profile; it loads a Workload identity locally and fetches launch bindings from STS.

See Configuration Order.

Related: FAQ-015, FAQ-028

FAQ-028Runtime

Does caracal run renew injected credentials?

No. It fetches bindings and mints each credential once before starting the child. The child receives a scrubbed environment and exits with those credentials’ existing expiry. Use a Caracal SDK for long-running software that must exchange on demand.

See Run Workloads.

Related: FAQ-015, FAQ-027

FAQ-029Platform

Can Gateway proxy WebSockets?

No. Gateway proxies HTTP request/response traffic and streamed responses such as SSE, but strips hop-by-hop headers including Upgrade. Protect WebSocket services with an in-process verifier or framework adapter at the service edge.

See Proxy Through Gateway and Verification Layer Overview.

Related: FAQ-002, FAQ-016

FAQ-030Operations

Why did retrying an STS exchange create uncertainty?

Mandate issuance uses one network attempt. If the response is lost, the server might have minted successfully, so the SDK cannot prove that a retry is the same issuance. Reconcile the operation or explicitly retry according to the protected action’s idempotency contract. Session and Delegation creation are different: Coordinator uses durable idempotency receipts and can replay their creation response safely.

See Safe Retries and Idempotency.

Related: FAQ-016, FAQ-028

FAQ-031Platform

Which Caracal versions can I mix?

None intentionally. Caracal packages, images, chart metadata, and binaries release in lockstep and are tested as one version. Pin exact versions and upgrade them together. On the pre-1.0 line, patch releases preserve documented public behavior; minor releases can change public contracts.

See Compatibility and Release Map.

Related: FAQ-002, FAQ-032

FAQ-032Platform

Why does the documentation URL say v0.2 before v0.2.0 is released?

v0.2 is the configured first documentation target. Before stable v0.2.0, unversioned source is served on shareable /v0.2/ routes, but no snapshot exists. The stable release creates and registers that snapshot. RCs create no snapshot, and later v0.2.x patches update the same current minor.

See Documentation Versions.

Related: FAQ-031

Use Glossary when you need canonical terms for concepts, API names, web console labels, and examples.