Agents can propose patches to their own behavior:
- Prompts
- Policies
- Routing heuristics
- Tool configurations
Patches are data, not code. They must:
- Be versioned
- Be signed
- Pass tests
- Be auditable
- Be replay-safe
pub struct PatchProposal {
pub patch_type: PatchType,
pub target: String, // What to patch
pub patch: String, // Patch data
pub reasoning: String, // Why this change
pub test_requirements: Vec<String>,
}| Type | Target | Example |
|---|---|---|
Prompt |
System prompt | Update instructions |
Policy |
Decision policy | Change routing |
Routing |
Heuristic | Adjust weights |
Config |
Configuration | Update parameters |
Tools |
Tool set | Add/remove tool |
Propose -> Sign -> Test Gate -> Audit Gate -> Apply -> Log
|
v
Reject (with reason)
Patches must pass tests:
fn test_gate(patch: &PatchProposal) -> GateResult {
for test in &patch.test_requirements {
if !run_test(test)? {
return GateResult::Rejected {
reason: format!("Test failed: {}", test),
};
}
}
GateResult::Accepted
}Patches are reviewed:
fn audit_gate(patch: &PatchProposal) -> GateResult {
// Check for unsafe changes
// Verify reasoning is sound
// Ensure compatibility with existing state
}When a patch is applied:
Event {
kind: EventKind::PatchApplied,
payload: PatchAppliedPayload {
patch_type: PatchType::Prompt,
target: "system_prompt".to_string(),
patch_hash: Hash::from_canonical(&patch),
reasoning: "Improved clarity".to_string(),
},
}Rejected patches are logged:
Event {
kind: EventKind::PatchRejected,
payload: PatchRejectedPayload {
patch_hash: Hash::from_canonical(&patch),
reason: "Failed safety test".to_string(),
stage: "test_gate".to_string(),
},
}Patches must be replay-safe:
- Deterministic application
- No external dependencies
- Version controlled
- Reversible
- Patches are data: Never executable code
- All patches tested: Test gate is mandatory
- All patches logged: Full history
- Patches are signed: Authenticated source
- Replay safe: Can be re-applied deterministically