keyward.broker console
control plane offlineoffline
Docs / Concepts

The six words Keyward uses

Every other page assumes these. Five minutes here saves an hour of guessing.

Scope

A scope is a named slice of a provider's API — charges:read is "read charges and payment history" on Stripe. You never invent scope strings: for built-in providers they come from Keyward's catalog (checkboxes in the console, tables in the Provider reference), and each maps to an explicit list of methods and paths the gateway will proxy. Anything not mapped is denied — even with a valid key.

The two gates: secret scopes AND policies

A request must pass both of two checks, configured on two different pages:

GateWhereWhat it saysDenial reason
Secret's allowed scopesSecrets pagethe ceiling for this key — scopes not checked here can never be used, by anyonescope_not_allowed
Policy rulesPolicies pagedeny-by-default rules per agent / provider / scope — who may use what's under the ceilingpolicy_denied

A fresh org starts with one wildcard allow policy so the ceiling is the only gate while you try things out; tighten policies when you add more agents. The audit log's denial reason tells you which gate refused — scope_not_allowed means edit the secret, policy_denied means edit the policies. The most specific matching rule wins; when two rules are equally specific, deny wins.

Environments

An environment (dev / stage / prod, default prod) is an isolated set of secrets and policies. The string must match in three places: the secret, the policy, and the agent's KEYWARD_ENVIRONMENT. The console uses a picker everywhere so the names can't drift — a mismatch looks like unknown_provider (the secret exists, just not in the environment the agent asked for).

Proxy vs native

ModeWhat Keyward holdsHow the agent callsBest for
Proxy (gateway)the provider's static API keykw.gateway(provider, path)SaaS APIs with long-lived keys (all 14 built-ins + custom)
Nativea parent credential that can mint short-lived ones (AWS STS today)kw.get(provider, scope, ttl)providers with real token exchange — the agent gets a credential that expires on its own

The two don't mix: a native secret can't be called through gateway() (native_not_proxyable), and a proxy credential from get() isn't accepted by the upstream API directly.

Service-agent vs delegated

Service mode (the default in every example): the agent authenticates with its own kw_svc_… key and acts on its own authority — audit rows show the synthetic user svc:<agent-id>. Delegated mode: the agent passes the end user's identity token instead, and every audit row carries the real person who authorized the action. Start with service mode; switch to delegated when "which human asked for this?" matters.

Delegation chains

When an orchestrator agent hands work to a sub-agent, the sub-agent presents the orchestrator's credential rather than a user token. Keyward keeps the original human as sub and nests each hop in the RFC 8693 act chain — user → orchestrator → sub-agent — cryptographically bound so a hop can't be spliced in, capped at depth 5.

Attestation (“secret zero”)

A service key is still a secret — who guards the guard? For agents running somewhere with a workload identity (GitHub Actions, Kubernetes, cloud VMs), register an attestation_issuer: the broker then requires a fresh, verifiable OIDC token from that platform on every request and fails closed without it. No Keyward secret to leak at all.