Agent SwarmAgent Swarm
Guides

Scripts credential broker

How scripts authenticate to external APIs without raw secrets in source, args, or logs.

The scripts credential broker lets swarm scripts authenticate outbound fetch calls without receiving the raw secret in script source or arguments. A script sends a [REDACTED:<configKey>] placeholder in a request header or query parameter, and the runtime swaps that placeholder for the real config value only when the destination host is allowlisted.

This broker is part of the scripts-runtime fetch layer. It is not a dynamic MCP tool generator, and it does not expose a new SDK method to unwrap secrets.

Binding model

Bindings live in swarm_config under SCRIPT_CREDENTIAL_BINDINGS. The document can be either an array of bindings or an object with a bindings array:

{
  "bindings": [
    {
      "configKey": "GITHUB_TOKEN",
      "allowedHosts": ["api.github.com"],
      "headerTemplate": "Authorization: Bearer [REDACTED:GITHUB_TOKEN]",
      "scope": "global",
      "scopeId": null,
      "active": true
    }
  ]
}

Each binding has:

  • configKey — the config key to resolve with the normal swarm config resolution path.
  • allowedHosts — exact hostnames where this credential may be substituted.
  • headerTemplate — optional header shape containing the [REDACTED:<configKey>] placeholder.
  • queryTemplate — optional query shape like api_key=[REDACTED:VENDOR_API_KEY].
  • scope / scopeIdglobal, agent, or repo scoping for where the binding applies.
  • active — set to false to keep a binding in config but stop using it.

At least one of headerTemplate or queryTemplate is required.

Default GitHub binding

Fresh runtimes include a backward-compatible default binding:

{
  "configKey": "GITHUB_TOKEN",
  "allowedHosts": ["api.github.com"],
  "headerTemplate": "Authorization: Bearer [REDACTED:GITHUB_TOKEN]",
  "scope": "global",
  "scopeId": null,
  "active": true
}

If GITHUB_TOKEN resolves from swarm config or the process environment, scripts can call GitHub by sending the placeholder header:

await fetch("https://api.github.com/repos/desplega-ai/agent-swarm", {
  headers: {
    Authorization: "Bearer [REDACTED:GITHUB_TOKEN]",
  },
});

The script never sees the raw token. The fetch patch substitutes the header only when the request hostname is api.github.com.

Query-string credentials

Some APIs require credentials in the query string. Configure a queryTemplate for those APIs:

{
  "configKey": "VENDOR_API_KEY",
  "allowedHosts": ["api.vendor.example"],
  "queryTemplate": "api_key=[REDACTED:VENDOR_API_KEY]",
  "scope": "global",
  "active": true
}

Then the script sends the placeholder query value:

const url = new URL("https://api.vendor.example/v1/items");
url.searchParams.set("api_key", "[REDACTED:VENDOR_API_KEY]");

await fetch(url);

The broker does not add missing query parameters. It only replaces placeholders that are already present on allowlisted hosts.

Operator workflow

Lead agents manage bindings through the static credential-bindings MCP tool. The tool writes SCRIPT_CREDENTIAL_BINDINGS to swarm_config; the runtime reads that config when a script starts.

If you want scripts to call a typed external API instead of hand-written fetch() calls, pair the broker with the lead-only script-connections tool. That registry stores an OpenAPI spec, allowed hosts, and the optional backing credential binding, then generates a typed ctx.api.<slug> client for swarm scripts.

Typical flow:

  1. Create or update the credential binding with credential-bindings.
  2. Register the OpenAPI-backed API connection with script-connections.
  3. Call the generated ctx.api.<slug> helpers from the script instead of embedding raw URLs and auth logic in source.

Global-scope config mutations now live-reload the runtime, so updated bindings and script connections take effect without a manual /api/config/reload.

For manual config management, keep the binding document non-secret. The secret value belongs in the separate swarm config key named by configKey, such as VENDOR_API_KEY, with isSecret enabled.

Security boundary

The placeholder flow is:

  1. The script subprocess receives resolved binding metadata and secret values through the internal egressSecrets payload.
  2. eval-harness.ts installs the credential-broker fetch patch before user code runs.
  3. On each fetch, the patch checks the request hostname.
  4. If the hostname is in allowedHosts, placeholders in configured headers or query parameters are replaced with the real secret value.
  5. If the hostname is not allowlisted, the placeholder remains redacted.

This means a script can opt in to using a credential for an approved API without being able to redirect the same placeholder to another host and leak the secret.

Request-body and path substitution are intentionally not supported today. Add those only with a separate host-allowlisted substitution mode and tests that preserve the same placeholder discipline.

On this page