Fix workspace bootstrap context delivery for agents#402
Conversation
Seed workspace context through dedicated bootstrap events so agent messages stay clean, while keeping tool skills free of dynamic identity and token state.
Use directory-based SKILL.md locations for Claude, OpenCode, and OpenClaw so each adapter matches its skill discovery contract.
Ensure backend-created workspace and routine channels emit bootstrap events so agents receive runtime context before processing work. Also allow the connector's default events poll size.
|
@kdxcxs is attempting to deploy a commit to the Raphael's projects Team on Vercel. A member of the Team first needs to authorize it. |
zomux
left a comment
There was a problem hiding this comment.
Thorough Review — Changes Requested
This is a well-designed PR that fixes a real security issue (shared SKILL.md leaking agent identity across agents). The bootstrap event mechanism is sound and the per-process env var injection is the right approach.
Blocking
Routine channel rename is a breaking change
The channel naming changed from routines:<agent> to routine:<id>. Existing production routines using the old channel names will be orphaned — their events will land in channels nothing is listening to. This needs either:
- An Alembic migration to rename existing routine channels
- Backward-compatibility handling that recognizes both patterns
- Or at minimum, documentation of the migration path for existing deployments
Should Address
1. _emit_agent_bootstrap_event is imported as a private function across modules
routines.py and workspaces.py import _emit_agent_bootstrap_event from workspace_mod.py. If it's part of the module's public API, drop the underscore prefix.
2. Duplicated spawn/process boilerplate
Claude, Cursor, and Gemini adapters each have nearly identical _spawnXxxProcess and bootstrap methods (~50 lines each). Consider consolidating into the base adapter.
Positive Notes
- Security improvement — identity no longer hardcoded in shared skill files. Per-process env vars and target-filtered bootstrap events are the right approach.
- Good test coverage — 4 new test files covering bootstrap events, Cursor/Gemini adapters, skill paths, and bootstrap-before-message ordering.
- No migration files — uses existing EventRecord model, no schema changes.
- Bootstrap filtering is correct —
targetandtarget_agentsare properly checked before delivering events.
CI
- Ubuntu/macOS tests all pass (Node 18/20/22)
agent-smokeand Windows failures are pre-existing infrastructure issues
|
I addressed the public bootstrap emitter naming and added the routine channel migration. I’m leaving the adapter spawn/bootstrap consolidation for a follow-up PR because it touches three CLI adapters and is a structural refactor rather than part of the bootstrap context fix. |
|
Longer term, I think an event-driven backend would be a better fit for the workspace system, but we should not jump straight to a full message queue unless the product actually needs it. The backend already has an A cleaner direction would be to model important facts as durable events:
Side effects should then move into dedicated workers or consumers:
Adapters could subscribe to explicit lifecycle and message events instead of each adapter carrying more bespoke initialization logic. The database should remain the source of truth, with an event log or outbox providing reliable The best first step is likely a DB-backed outbox plus worker, not Kafka, RabbitMQ, or another full MQ immediately. For example, a Postgres I think a real event-driven backend also fits serverless architecture better. In a serverless setup, request handlers should ideally stay thin: validate input, persist state changes, and enqueue durable follow-up work. Long-running or failure-prone side effects such as routine firing, bootstrap dispatch, notifications, title generation, and adapter lifecycle coordination can then run in separate workers or triggered functions with their own retry policies. A DB-backed outbox is a good stepping stone here because it keeps the database as the source of truth while still giving us reliable async execution. Later, if we move more of the backend to serverless infrastructure, the same event boundaries can map naturally to queue consumers, scheduled functions, or pub/sub subscribers without rewriting the domain flow. |
Summary
.cursor/skills/openagents-workspace/SKILL.md.workspace.agent.bootstrapevents for backend-created channels so agents receive runtime context before handling messages.Why
Bootstrap Mechanism
workspace.agent.bootstrapevent when an agent becomes a participant in a channel, including workspace-created default sessions, channel create/join flows, message-routing auto-joins, and routine channels.workspace.*events and processesworkspace.agent.bootstrapbefore regularworkspace.message.postedevents in the same batch.Test plan
node --test test/bootstrap-event.test.js test/cursor.test.js test/workspace-client.test.js.venv/bin/pytest tests/test_channel_membership.py tests/test_routines.py -q.venv/bin/pytest tests/test_events.py::TestPollEvents::test_poll_accepts_connector_default_limit -qcursor-alphaconsumed the persisted bootstrap event.