This repository was archived by the owner on Feb 25, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 50
feat(warm): Warm Agents — deterministic orchestration with blast-radius enforcement #502
Closed
Closed
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
1eaac8c
feat(warm): add Warm Agents Phase 1 prototype — schemas, scorer, inva…
Mnehmos d80b67d
feat(warm): Phase 2 — scheduler, policy, capability registry, --warm …
Mnehmos 6b3b818
feat(warm): Phase 3 — MCP health, rollback, replay, comprehensive tests
Mnehmos 732f42b
feat(warm): Phase 4 — wire warm agents into execution pipeline
Mnehmos 60bf8e9
feat(warm): wire warm agents into TUI mode via --warm flag
Mnehmos 37b1d1e
fix(warm): use direct module imports instead of barrel to prevent cir…
Mnehmos 5411e36
feat(warm): hierarchical blast-radius enforcement for sub-agents
Mnehmos ac8c243
test(warm): add standalone audit demo script
Mnehmos b13b941
fix(warm): suppress log noise in audit demo for clean output
Mnehmos File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -34,6 +34,7 @@ target | |
| opencode-dev | ||
| logs/ | ||
| *.bun-build | ||
| .local/ | ||
|
|
||
| # Telemetry ID | ||
| telemetry-id | ||
| telemetry-id | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| # Warm Agents Orchestration — Architect Prompt (Internal) | ||
|
|
||
| Use this prompt when you want an architecture-focused design pass for introducing **Warm Agents** into Kilo. | ||
|
|
||
| ## Prompt | ||
|
|
||
| You are the **Architect Agent** for Kilo. Your mission is to design a deterministic, stateful orchestration system called **Warm Agents**. | ||
|
|
||
| ### Core Intent | ||
| Design an architecture where agent execution behaves like a high-reliability dispatch system: | ||
| - **Validate intent** before action | ||
| - **Control scope** before mutation | ||
| - **Persist state** for recovery, handoff, and CI/CD replay | ||
|
|
||
| ### Mental Model: Mining Fleet Operations (Morenci-style parallels) | ||
| Ground your design in operational control concepts used in large haul-truck fleets: | ||
| - **MIS-style status tracking**: every agent and task has explicit lifecycle state and telemetry | ||
| - **JIT dispatching**: assign work to the warmest qualified agent at the right time, not first-available | ||
| - **TPS discipline**: preserve flow, reduce queue buildup, and minimize rework loops | ||
| - **Safety interlocks**: no movement without preconditions; no silent failure; deterministic stop modes | ||
|
|
||
| Translate this into software architecture with strict contracts, not narrative guidance. | ||
|
|
||
| ### Required Outcomes | ||
| Produce an architecture proposal with: | ||
| 1. **Subsystem map** for Warm Agents (scheduler, state store, capability registry, invariant middleware, replay/rollback) | ||
| 2. **Typed lifecycle model** for agent/task/session states | ||
| 3. **Deterministic routing rules** for selecting/rehydrating warm agents | ||
| 4. **State durability design** across process restarts and `--auto` unattended runs | ||
| 5. **Safety model** for blast-radius control, postcondition checks, and rollback behavior | ||
| 6. **MCP-aware capability routing** that adapts to live tool availability changes | ||
| 7. **Migration plan** from current Kilo orchestration to Warm Agents with low merge-conflict footprint | ||
|
|
||
| ### Hard Constraints | ||
| - Assume Kilo’s current architecture has: | ||
| - durable session/message storage, | ||
| - mixed in-memory runtime state, | ||
| - prompt-led orchestration behavior, | ||
| - tool schema validation but limited cross-tool invariants, | ||
| - `--auto` with permission auto-approval. | ||
| - Keep proposals compatible with current code organization in `packages/opencode/src/`. | ||
| - Prefer additive seams over invasive rewrites. | ||
| - Separate **prototype scope** from **production-hardening scope**. | ||
|
|
||
| ### Deliverable Format | ||
| Return exactly these sections: | ||
|
|
||
| 1. **Executive Summary** (max 10 bullet points) | ||
| 2. **Architecture Blueprint** | ||
| - Components | ||
| - Data flows | ||
| - Failure domains | ||
| 3. **State & Contract Schema** | ||
| - Agent state machine | ||
| - Task state machine | ||
| - Session continuity schema | ||
| 4. **Deterministic Orchestration Policy** | ||
| - Rule evaluation order | ||
| - Override/deny semantics | ||
| - Audit log model | ||
| 5. **Warmness Model** | ||
| - How warm context is scored | ||
| - Expiration/staleness rules | ||
| - Rehydration strategy | ||
| 6. **Safety Harness Design for `--auto`** | ||
| - Snapshot strategy | ||
| - Blast radius declaration | ||
| - Rollback protocol | ||
| - Structured failure report schema | ||
| 7. **MCP Lifecycle Awareness Plan** | ||
| - Health checks | ||
| - Tool schema drift handling | ||
| - Runtime routing fallback | ||
| 8. **Implementation Plan** | ||
| - 3 phases (prototype, integration, hardening) | ||
| - Files likely touched | ||
| - Risks and mitigations | ||
| 9. **60-Second Demo Script** | ||
| - Concrete command flow | ||
| - Expected observable behavior | ||
| 10. **Acceptance Criteria** | ||
| - Determinism checks | ||
| - Recovery checks | ||
| - Safety checks | ||
|
|
||
| ### Quality Bar | ||
| Your design is acceptable only if a senior developer can answer all three: | ||
| - What was the agent trying to do? | ||
| - What was it allowed to change? | ||
| - What state survives process death? | ||
|
|
||
| If any answer is unclear, revise the design until explicit. | ||
|
|
||
| --- | ||
|
|
||
| ## Optional Usage Note | ||
| Use this prompt as internal architecture guidance while exploring contributions around deterministic orchestration and warm-context reuse. |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -810,6 +810,19 @@ export namespace SessionPrompt { | |||||
| inputSchema: jsonSchema(schema as any), | ||||||
| async execute(args, options) { | ||||||
| const ctx = context(args, options) | ||||||
| // kilocode_change start - warm agent blast-radius enforcement | ||||||
| const warmCheck = await (async () => { | ||||||
| if (!(globalThis as any).__warmContext?.enabled && process.env.KILO_WARM !== "1") return undefined | ||||||
| const { WarmIntegration } = await import("../warm/integration") | ||||||
| return WarmIntegration.checkTool(item.id, args, ctx.sessionID) | ||||||
| })() | ||||||
| if (warmCheck && !warmCheck.allowed) { | ||||||
| return { | ||||||
| output: `[warm] Tool "${item.id}" blocked by blast-radius enforcement: ${warmCheck.reason}`, | ||||||
| title: `[warm] blocked`, | ||||||
| } | ||||||
| } | ||||||
| // kilocode_change end | ||||||
| await Plugin.trigger( | ||||||
| "tool.execute.before", | ||||||
| { | ||||||
|
|
@@ -832,6 +845,12 @@ export namespace SessionPrompt { | |||||
| }, | ||||||
| result, | ||||||
| ) | ||||||
| // kilocode_change start - warm agent audit logging | ||||||
| if (warmCheck?.logged) { | ||||||
| const { WarmIntegration } = await import("../warm/integration") | ||||||
| await WarmIntegration.logToolExecution(ctx.sessionID, item.id, args, 0).catch(() => {}) | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [WARNING]: Empty Two issues:
Suggested change
|
||||||
| } | ||||||
| // kilocode_change end | ||||||
| return result | ||||||
| }, | ||||||
| }) | ||||||
|
|
@@ -847,6 +866,19 @@ export namespace SessionPrompt { | |||||
| item.execute = async (args, opts) => { | ||||||
| const ctx = context(args, opts) | ||||||
|
|
||||||
| // kilocode_change start - warm agent blast-radius enforcement for MCP tools | ||||||
| const warmCheck = await (async () => { | ||||||
| if (!(globalThis as any).__warmContext?.enabled && process.env.KILO_WARM !== "1") return undefined | ||||||
| const { WarmIntegration } = await import("../warm/integration") | ||||||
| return WarmIntegration.checkTool(key, args, ctx.sessionID) | ||||||
| })() | ||||||
| if (warmCheck && !warmCheck.allowed) { | ||||||
| return { | ||||||
| content: [{ type: "text" as const, text: `[warm] MCP tool "${key}" blocked by blast-radius enforcement: ${warmCheck.reason}` }], | ||||||
| } | ||||||
| } | ||||||
| // kilocode_change end | ||||||
|
|
||||||
| await Plugin.trigger( | ||||||
| "tool.execute.before", | ||||||
| { | ||||||
|
|
||||||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,6 +125,17 @@ export const TaskTool = Tool.define("task", async (ctx) => { | |
| using _ = defer(() => ctx.abort.removeEventListener("abort", cancel)) | ||
| const promptParts = await SessionPrompt.resolvePromptParts(params.prompt) | ||
|
|
||
| // kilocode_change start - warm agents: create scoped sub-task for sub-agent | ||
| let warmSubTask: { taskID: string; parentTaskID: string; narrowed: boolean; scope: string[]; previousTask?: any } | undefined | ||
| if ((globalThis as any).__warmContext?.enabled || process.env.KILO_WARM === "1") { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SUGGESTION: This check duplicates the logic in const { WarmIntegration } = await import("../warm/integration")
if (WarmIntegration.isEnabled()) {This keeps the warm-context detection logic in one place and avoids direct |
||
| const { WarmIntegration } = await import("../warm/integration") | ||
| warmSubTask = await WarmIntegration.createSubTask( | ||
| ctx.sessionID, | ||
| params.prompt, | ||
| ) | ||
| } | ||
| // kilocode_change end | ||
|
|
||
| const result = await SessionPrompt.prompt({ | ||
| messageID, | ||
| sessionID: session.id, | ||
|
|
@@ -142,10 +153,26 @@ export const TaskTool = Tool.define("task", async (ctx) => { | |
| parts: promptParts, | ||
| }) | ||
|
|
||
| // kilocode_change start - warm agents: restore parent task after sub-agent completes | ||
| if (warmSubTask?.previousTask) { | ||
| const { WarmIntegration } = await import("../warm/integration") | ||
| await WarmIntegration.completeSubTask(ctx.sessionID, warmSubTask.previousTask) | ||
| } | ||
| // kilocode_change end | ||
|
|
||
| const text = result.parts.findLast((x) => x.type === "text")?.text ?? "" | ||
|
|
||
| // kilocode_change start - warm agents: include scope info in output | ||
| const scopeInfo = warmSubTask?.narrowed | ||
| ? `\n[warm] Sub-task scope: ${warmSubTask.scope.join(", ")} (narrowed from parent)` | ||
| : warmSubTask | ||
| ? `\n[warm] Sub-task scope: ${warmSubTask.scope.join(", ")} (inherited from parent)` | ||
| : "" | ||
| // kilocode_change end | ||
|
|
||
| const output = [ | ||
| `task_id: ${session.id} (for resuming to continue this task if needed)`, | ||
| scopeInfo, | ||
| "", | ||
| "<task_result>", | ||
| text, | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WARNING: Direct
(globalThis as any).__warmContextaccess bypasses the centralizedWarmIntegration.getContext()that was created specifically to encapsulate this.Since
WarmIntegrationis already imported on line 543, consider usingWarmIntegration.getContext()here instead for consistency and type safety. The same applies to line 540.