Skip to content

delegates: expose per-delegate env in the console editor, with a secret tier for values like API keys #2114

Description

@mabry1985

Gap

The delegates runtime already supports a per-delegate env: map — parsed in plugins/delegates/adapters.py (raw.get("env")), merged over the process env at ACP spawn, PATH-aware in the handshake probe (#1299), and redacted in /api/delegates views (_redact_env). But the console delegate editor is driven by each adapter's config_schema(), and none of them expose an env field — so the only ways to author an env-carrying delegate are:

  • hand-editing langgraph-config.yaml (secrets like ANTHROPIC_AUTH_TOKEN land in plaintext config), or
  • a wrapper script that exports the env and execs the agent (works, but invisible to the console, and each user reinvents key-sourcing).

This bites immediately for the common case: Claude Code pointed at an alternate Anthropic-compatible gateway (e.g. DeepSeek's /anthropic endpoint) — the whole delegate is just claude-agent-acp plus ~8 env vars (ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN, ANTHROPIC_MODEL, ANTHROPIC_DEFAULT_*_MODEL, …), one of which is a secret. Same shape as the already-shipped per-delegate model pin (env: {ANTHROPIC_MODEL: opus}).

Proposal

  1. Editor surface: add an env editor (key/value rows) to the delegate create/edit form — likely a new FieldSpec kind ("envmap") so every adapter type gets it, with per-row secret toggle.
  2. Secret tier: a row marked secret stores its value in the secrets.yaml overlay (the _secret resolution pattern other adapter fields already use: explicit overlay value wins, else a named host env var), never in langgraph-config.yaml. Views stay redacted (_redact_env already does this half).
  3. Semantics stay as shipped (document them in the form help): values are verbatim strings — no ${VAR} expansion — merged over the inherited process env; PATH in the map overlays the probe path.
  4. Bundle/archetype tie-in: a bundle-shipped delegate whose env values carry ${input} placeholders should resolve through the Console: create-time "prompt-for-value" picker for bundle ${input} templates (mcp servers + secrets) #2041 create-time prompt-for-value picker (same inputs contract as mcp-catalog.json), closing the same loop as Archetype/bundle seam: env + secrets seeding #2014 for delegate credentials.

Refs

plugins/delegates/adapters.py (env parse at ~L591, merged-PATH probe ~L743, _secret ~L95), plugins/delegates/api.py (_redact_env), ADR 0025, ADR 0080 (no host-env auto-copy), #2041, #2014.

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-infoIssue is missing required sections — see CONTRIBUTING.md (silent issue gate).team-readyTriaged and approved for autonomous team dispatch — the ONLY intake gate the board pipeline accepts

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions