Skip to content

workspace.yaml agents

The software_delivery.agents block configures which agent client LumenFlow prefers, which agent names are considered part of the workspace roster, and which of those agents become mandatory for matching code paths.

Client configuration is descriptive, not authority. Every harness uses the versioned universal capability contract for methodology, WU operations, lifecycle, initiative planning, delegation, model/effort control, and application attestation. Model control, effort control, and application attestation remain separate outcomes, including model-only or effort-only host evidence. Missing or unknown capabilities fail safe; client names and host memory/cache cannot grant authority or synthesize a canonical brief. The release-evidence-indexed contract digest and lifecycle-issued brief/WU/workspace/HEAD evidence must all match before routing is verified.

software_delivery:
  agents:
    defaultClient: claude-code
    roster:
      - general-purpose
      - lumenflow-pm
      - test-engineer
      - code-reviewer
      - bug-triage
      - lumenflow-enforcer
      - initiative-architect
    mandatory:
      names: []
      triggers: {}
    clients:
      codex-cli:
        agentsDir: .agents/agents

Preferred client ID when a command needs an agent client and the caller did not pass one explicitly.

  • Type: string
  • Default: claude-code

The workspace-level list of agent names the orchestration surface should treat as valid. When you omit this field, LumenFlow uses the built-in framework roster:

  • general-purpose

  • lumenflow-pm

  • test-engineer

  • code-reviewer

  • bug-triage

  • lumenflow-enforcer

  • initiative-architect

  • Type: string[]

  • Default: the built-in agent roster above

Subset of agents.roster that may be enforced as mandatory when a matching trigger fires.

  • Type: string[]
  • Default: []

Maps mandatory agent names to glob patterns. If a WU touches a matching path, that agent becomes mandatory for the workflow surfaces that consume mandatory-agent rules.

  • Type: Record<string, string[]>
  • Default: {}

Example:

software_delivery:
  agents:
    roster:
      - custom-security-reviewer
    mandatory:
      names:
        - custom-security-reviewer
      triggers:
        custom-security-reviewer:
          - auth/**
          - supabase/migrations/**

Optional compatibility metadata for a project-owned client agent-definition directory. LumenFlow does not create, modify, or treat this directory as a managed surface; it remains separate from the workspace roster and canonical .lumenflow/skills/ contract.

  • Type: string
  • Default: inherits the global directory default for that client

Declarative capability flags for a client, consumed by the idle-orchestrator push adapter port (ADR-019’s idle-session delivery amendment, WU-3782). This key previously carried a different, vendor capability-resolution shape (native_signal_hooks, settings_projection, enforcement_hooks, brief_renderer) that was retired: LumenFlow does not project settings, generate hooks, or gate brief rendering by client membership. It answers one narrow capability question — “does this client expose a native push channel this workspace can actually use to wake an idle session?” — and it is data-driven: setting the flag never by itself proves the channel is usable, it only tells LumenFlow to attempt a real per-host delivery instead of skipping straight to the always-available fallback.

  • Type: object
  • Default: { harnessPush: false } for every client, including the built-in ones. No client declares this on by default.
FieldTypeMeaning
harnessPushbooleanThis client declares a native push/notification channel to its own session. Selection is by this flag alone, never by client name. Default: false.
software_delivery:
  agents:
    clients:
      claude-code:
        capabilities:
          harnessPush: true

Declaring the flag is not the same as it working. Once harnessPush: true is declared, the push port attempts a REAL per-client delivery (vendor names live only in that adapter code, never in this config) and reports its own outcome. As of this WU, LumenFlow ships adapters for claude-code and codex-cli, and both report an explicit unsupported-on-host result rather than a silent fake success — see the ADR-019 idle-session delivery amendment for why. An unknown/BYOK client id that sets the flag with no matching adapter gets the same honest treatment: an unsupported-on-host result naming the client id, never a thrown error and never a silent no-op. The durable JSONL wake-channel record mem-watch-fallback writes is the real delivery for every host today — orchestrate:monitor --watch or mem:watch is the prescribed orchestrator-side watcher regardless of this flag.

GitHub Actions runner label(s) for the generated .github/workflows/lumenflow-ci.yml enforcement job. lumenflow:enable and lumenflow:upgrade regenerate that workflow from a template whose default is ubuntu-latest; setting this field is what makes a self-hosted runner pool survive that regeneration instead of silently reverting to paid GitHub-hosted minutes on the next enable/upgrade (WU-3941).

  • Type: string | string[]
  • Default: unset (the generated workflow keeps the template’s ubuntu-latest default)
software_delivery:
  agents:
    lifecycle_enforcement:
      ci:
        runs_on:
          - self-hosted
          - Linux
          - X64
          - general-ci

Only runs_on is modeled today. The rest of agents.lifecycle_enforcement (enabled, policy_version, integrity_manifest) is managed by lumenflow:enable/lumenflow:disable, not hand-edited.

Nested agent config merges with defaults instead of replacing the whole structure. For example, this partial override keeps the built-in roster and default client while only adding trigger rules:

software_delivery:
  agents:
    mandatory:
      triggers:
        custom-agent:
          - auth/**

Likewise, setting only mandatory.names no longer removes the default mandatory.triggers object.

Agent configuration does not grant lifecycle authority. Repository-owned delegators and the integrity manifest protect lifecycle evidence for every declared client, and only an enforced lumenflow:doctor state is certifying. A hostile unsandboxed process with the same OS-user authority can replace local code, hooks, or receipts; preventing that requires an OS sandbox or protected remote/server authority. Disabled and uninstalled consumers cannot claim lifecycle certification.

If your workspace previously only used:

software_delivery:
  agents:
    defaultClient: codex-cli

you do not need to change anything. That configuration still works.

Add the new fields only when you need them:

  1. Add agents.roster when you want to declare a custom or narrowed set of agent names.
  2. Add agents.mandatory.names when some of those agents should become enforceable.
  3. Add agents.mandatory.triggers when you want code-path-based mandatory-agent detection.
  4. Add agents.clients.<client>.agentsDir when a client should resolve agent definitions from a non-default directory.
  5. Add agents.clients.<client>.capabilities.harnessPush only when you want the idle-orchestrator push port to attempt a real per-host delivery for that client instead of going straight to the always-available mem-watch-fallback adapter. Omitting it (the default for every client) never loses delivery — the fallback adapter already covers every host.

The authoritative schema enforces two cross-field rules:

  • Every name in agents.mandatory.names must also appear in agents.roster.
  • Every key in agents.mandatory.triggers must also appear in agents.mandatory.names.

Those rules keep the roster, mandatory list, and trigger map aligned as you customize the workspace.