Skip to content

[Feature] synchronize Claude Code agent definitions during proxy startup #2200

Closed

Description

@brunoflma

Area

Service lifecycle

What are you trying to accomplish?

Keep the generated Claude Code agent roster synchronized with the live OpenCodex configuration whenever the proxy daemon starts, including background starts and service restarts.

What prevents this today?

The files ~/.claude/agents/ocx-*.md are derived artifacts from config.json / subagentModels. In the current dev path, injectClaudeAgentDefs() runs at the explicit ocx claude launch and syncClaudeAgentDefsBestEffort() runs after selected Management API mutations. A manual edit to config.json, a Task Scheduler/background service start, or a plain proxy restart does not necessarily execute either hook.

That leaves stale or orphaned definitions loaded by Claude Code even though the live config is already correct. We observed a dead ocx-gemini-3-6-flash.md surviving while config pointed to the replacement model until a supported API mutation forced a sync.

What should OpenCodex do?

During the idempotent proxy startup/ensure routine, reconcile the owned ocx-*.md files from the current config and context-window map. The startup hook should:

  • write definitions for the current enabled subagentModels roster;
  • remove stale files previously owned by OpenCodex;
  • respect claudeCode.enabled and claudeCode.injectAgents disablement;
  • remain best-effort so provider discovery failure does not prevent the proxy from starting;
  • be safe to run repeatedly on every daemon/service start.

Example usage or interface

  1. Edit config.json so subagentModels replaces gpt-5.6-sol with gemini-3.7-flash.
  2. Start or restart the proxy through Task Scheduler / ocx restart.
  3. Before invoking Claude Code, ~/.claude/agents/ocx-gemini-3-7-flash.md should exist and the old ocx-gpt-5-6-sol.md should be gone.
  4. Running the same start again should produce the same files without duplicates or churn.

Alternatives or workarounds

The current workaround is to repeat a supported Management API mutation (for example PUT /api/subagent-models with the already-saved list) or invoke ocx claude before using Claude Code. Both are surprising for a daemon/service workflow and do not repair the roster at the moment a background service becomes healthy.

Additional context

The launch-time injection implementation is in src/claude/agents-inject.ts; current call sites are src/cli/claude.ts, src/server/system-env.ts, and selected management routes. The gap is the absence of an idempotent startup hook in the proxy start/ensure path. The issue was re-verified against the v2.28.0 migration stack (commit c0dcef24) after typecheck and migration-focused tests passed.

Related lifecycle/config synchronization code should be reused rather than adding a second roster format.

Activity

  1. added
    enhancementNew feature or request
    proxyHTTP proxy, routing, reverse-proxy / management auth
    on Aug 20, 2026
  2. lidge-jun commented on Aug 20, 2026

    @lidge-jun
    Owner

    리뷰 · 우선순위 54 / 80

    데몬 시작이 로스터를 안 맞추는 거 맞음. injectClaudeAgentDefs는 src/cli/claude.ts:330이랑 src/server/system-env.ts:415랑 매니지먼트 mutation 뒤에만 돈다. startServer (src/server/index.ts:495)는 컨피그 마이그레이션이랑 캐시 무효화는 해도 에이전트 md 싱크는 안 함. 백그라운드 ocx start/스케줄러가 그 구멍임.

    구현은 이미 있음. src/claude/agents-inject.ts:249가 claudeCode.enabled / injectAgents false면 소유 파일을 지우고, 아니면 syncClaudeAgentDefs로 현재 로스터를 씀. 포맷을 새로 만들 거 아님. management-api.ts:195의 syncClaudeAgentDefsBestEffort를 부팅에도 한 번 호출하면 됨.

    best-effort가 맞음. 프로바이더 디스커버리 실패로 프록시가 못 뜨면 안 됨. 매니지먼트 훅은 이미 try/catch로 삼킴. 스타트업도 같게. 반복 실행 안전하다고 함수가 이미 idempotent임.

    수동 config.json 편집은 저장 훅이 없어서 재시작 전까지 낡은 md가 남는 게 정상임. 그래서 스타트업 훅이 필요함. GUI에서 subagent 바꾸면 지금 mutation 경로로 싱크됨. 데몬만 빠짐.

    types.ts 스플릿이랑 상관 없음. 2.28 블로커도 아님. 닫을 중복 아님.

    해결방안: startServer 끝쪽(마이그레이션/baseline 다음, listen 전후 상관없음. 실패해도 서버는 떠야 함)에 기존 injectClaudeAgentDefs/syncClaudeAgentDefsBestEffort를 한 번 넣음. 새 로스터 포맷 금지. claudeCode.enabled/injectAgents 가드는 그대로.

    이 댓글은 grok-bot이 작성했습니다

  3. self-assigned this
    on Aug 20, 2026
  4. Ingwannu commented on Aug 20, 2026

    @Ingwannu
    Owner

    Confirmed against current dev (f2ebd3067). The existing call in system-env.ts does not close this gap cross-platform: it sits inside injectSystemEnv, which returns before agent synchronization on non-macOS systems and when claudeCode.systemEnv is disabled. The other call sites cover explicit ocx claude launches and selected Management API writes, not an ordinary Linux/Windows service restart.

    I am taking this as a focused lifecycle fix. I will reuse the existing owned-file reconciliation and context-window builder, call it from the proxy startup/ensure path, keep it best-effort and idempotent, preserve claudeCode.enabled / injectAgents pruning semantics, and avoid adding a second roster format. Tests will cover stale-file removal on startup, disabled pruning, repeated convergence, catalog failure fallback, and the non-macOS path.

  5. Ingwannu commented on Aug 20, 2026

    @Ingwannu
    Owner

    Implemented in #2202. The startup hook reuses the existing owned Claude-agent reconciliation outside startServer, remains best-effort/idempotent, preserves disabled pruning, and covers Linux/Windows/background startup paths.

    The branch is now rebased onto current dev at 5df962b0d952e1143b34249eeb1e1d405f181b98. Focused tests passed 62/62 and typecheck/diff-check passed locally. I have requested @lidge-jun exact-head review and will leave this issue open until the PR is approved and merged.

  6. Ingwannu commented on Aug 21, 2026

    @Ingwannu
    Owner

    Completed and merged into dev via #2202 (merge commit 1ca08e6). The startup path now reuses the existing best-effort, idempotent Claude agent reconciliation, including disabled-state pruning and non-macOS/background service startup coverage. Closing this as completed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestproxyHTTP proxy, routing, reverse-proxy / management auth

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions