Summary
Each project should be able to carry its own agent configuration (model, flags, permission mode, agent-specific keys), but today there is no durable per-project agent config. The legacy TS version resolved this from agent-orchestrator.yaml ("global vs project config resolution"); the Go rewrite split global settings into env vars and project identity into the projects table, but the per-project agent config half was never wired to storage.
The type-level scaffolding already exists — it just has no data source.
Current state
Wired today (per-session, at spawn):
ports.SpawnConfig carries Harness, Prompt, AgentRules (backend/internal/ports/session.go:7).
- Empty
Harness falls back to the daemon-global AO_AGENT default (backend/internal/daemon/lifecycle_wiring.go:142).
Designed but NOT wired:
ports.AgentConfig (map[string]any) — "values loaded from the selected agent's config section" (backend/internal/ports/agent.go:54).
ports.ConfigSpec / ConfigField — typed, adapter-declared config keys (backend/internal/ports/agent.go:57).
LaunchConfig.Config — the carrier into the launch command (backend/internal/ports/agent.go:85).
The gaps:
projects table has no agent-config columns — only id, path, repo_origin_url, display_name, registered_at, archived_at (backend/internal/storage/sqlite/migrations/0001_init.sql:8).
- At spawn,
LaunchConfig is built with Config left empty (backend/internal/session_manager/manager.go:139).
claudecode.GetConfigSpec returns an empty spec ("no agent-specific config keys yet", backend/internal/adapters/agent/claudecode/claudecode.go:85).
Proposed slice
Following the rewrite's patterns (env for global, DB rows for per-project, validation owned by adapters):
- Storage — persist per-project agent config keyed by
project_id (e.g. a projects.agent_config JSON column, or a project_agent_config table keyed by project_id + harness). Add sqlc queries + migration.
- Resolution — in
startSession / session_manager, load the project's config and populate LaunchConfig.Config before GetLaunchCommand.
- Validation — each adapter validates its own keys against its
ConfigSpec ("Agent adapters own validation for their custom keys").
- CLI/API surface — set/get per-project agent config (e.g. extend
ao project + a projects controller route).
Out of scope
- Pinning a default
harness per project (separate concern; can be a follow-up using the same storage).
- Notifier/tracker/SCM per-project config (this issue is scoped to agent config).
Acceptance criteria
- A project can store agent config that survives daemon restart.
- A spawn for that project receives the resolved
AgentConfig in LaunchConfig.Config.
- Invalid keys/values are rejected by the owning adapter with a clear error.
- Works OS-agnostically (macOS/Linux/Windows); no new env-only config for per-project state.
🤖 Generated with Claude Code
Summary
Each project should be able to carry its own agent configuration (model, flags, permission mode, agent-specific keys), but today there is no durable per-project agent config. The legacy TS version resolved this from
agent-orchestrator.yaml("global vs project config resolution"); the Go rewrite split global settings into env vars and project identity into theprojectstable, but the per-project agent config half was never wired to storage.The type-level scaffolding already exists — it just has no data source.
Current state
Wired today (per-session, at spawn):
ports.SpawnConfigcarriesHarness,Prompt,AgentRules(backend/internal/ports/session.go:7).Harnessfalls back to the daemon-globalAO_AGENTdefault (backend/internal/daemon/lifecycle_wiring.go:142).Designed but NOT wired:
ports.AgentConfig(map[string]any) — "values loaded from the selected agent's config section" (backend/internal/ports/agent.go:54).ports.ConfigSpec/ConfigField— typed, adapter-declared config keys (backend/internal/ports/agent.go:57).LaunchConfig.Config— the carrier into the launch command (backend/internal/ports/agent.go:85).The gaps:
projectstable has no agent-config columns — onlyid, path, repo_origin_url, display_name, registered_at, archived_at(backend/internal/storage/sqlite/migrations/0001_init.sql:8).LaunchConfigis built withConfigleft empty (backend/internal/session_manager/manager.go:139).claudecode.GetConfigSpecreturns an empty spec ("no agent-specific config keys yet",backend/internal/adapters/agent/claudecode/claudecode.go:85).Proposed slice
Following the rewrite's patterns (env for global, DB rows for per-project, validation owned by adapters):
project_id(e.g. aprojects.agent_configJSON column, or aproject_agent_configtable keyed byproject_id+harness). Add sqlc queries + migration.startSession/session_manager, load the project's config and populateLaunchConfig.ConfigbeforeGetLaunchCommand.ConfigSpec("Agent adapters own validation for their custom keys").ao project+ a projects controller route).Out of scope
harnessper project (separate concern; can be a follow-up using the same storage).Acceptance criteria
AgentConfiginLaunchConfig.Config.🤖 Generated with Claude Code