Door governor: runtime-agent judge (Kimi-as-judge on the subscription)
The §15 governor can now be judged by a ZeroClaw runtime agent instead of a server-side registry/API model. ZeroClawDriveExecutor::judge drives an agent with the governor prompt and parses ALLOW/DENY (fail-open). mcp_door routes to it when CLAWMATES_JUDGE_MODEL=runtime:<alias>. This unblocks Kimi-as-judge with NO Kimi Platform key: Kimi runs on the membership via kimi_cli, so CLAWMATES_JUDGE_MODEL=runtime:judge_kimi makes the coding agent the governor. (Same path works for any subscription-only model.) cm-runtime re-exports judge_model. clippy clean. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
2fcec622fb
commit
3402a3b56d
@@ -153,7 +153,18 @@ async fn policy_decide(
|
|||||||
category.map(|c| c.as_str()).unwrap_or("none"),
|
category.map(|c| c.as_str()).unwrap_or("none"),
|
||||||
serde_json::to_string(args).unwrap_or_default()
|
serde_json::to_string(args).unwrap_or_default()
|
||||||
);
|
);
|
||||||
let (allow, reason) = state.runtime.judge(system, &request).await;
|
// `CLAWMATES_JUDGE_MODEL=runtime:<alias>` routes the governor through a
|
||||||
|
// ZeroClaw runtime agent (e.g. Kimi via kimi_cli on the subscription) —
|
||||||
|
// no platform API key needed. Otherwise the server-side registry judge.
|
||||||
|
let judge_model = cm_runtime::judge_model();
|
||||||
|
let (allow, reason) = if let Some(alias) = judge_model.strip_prefix("runtime:") {
|
||||||
|
match crate::topology_exec::ZeroClawDriveExecutor::from_env() {
|
||||||
|
Ok(exec) => exec.judge(alias.trim(), system, &request).await,
|
||||||
|
Err(e) => (true, format!("governor unreachable (fail-open): {e}")),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
state.runtime.judge(system, &request).await
|
||||||
|
};
|
||||||
if !allow {
|
if !allow {
|
||||||
return PolicyOutcome::Deny(format!("governor agent vetoed — {reason}"));
|
return PolicyOutcome::Deny(format!("governor agent vetoed — {reason}"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -179,6 +179,23 @@ impl ZeroClawDriveExecutor {
|
|||||||
Ok(outcome)
|
Ok(outcome)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Use a runtime agent as a governance judge: drive `alias` with the judge
|
||||||
|
/// prompt and parse the verdict (`DENY` anywhere ⇒ deny, else allow). This
|
||||||
|
/// lets a **subscription-only** model (e.g. Kimi via `kimi_cli`) be the judge
|
||||||
|
/// with no platform API key — the registry/SDK path GLM and Kimi can't take.
|
||||||
|
/// Fail-open (returns `(true, …)`) so a judge outage never halts agents.
|
||||||
|
pub async fn judge(&self, alias: &str, system: &str, user: &str) -> (bool, String) {
|
||||||
|
let prompt = format!("{system}\n\n{user}");
|
||||||
|
match self.drive(alias, &prompt).await {
|
||||||
|
Ok(outcome) => {
|
||||||
|
let text = outcome.output.trim().to_string();
|
||||||
|
let allow = !text.to_uppercase().contains("DENY");
|
||||||
|
(allow, text)
|
||||||
|
}
|
||||||
|
Err(e) => (true, format!("governor unreachable (fail-open): {e}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Read frames until a terminal (`done`/`error`/`approval_request`) event.
|
/// Read frames until a terminal (`done`/`error`/`approval_request`) event.
|
||||||
async fn drain<S>(ws: &mut S) -> Result<TurnOutcome, OrchestratorError>
|
async fn drain<S>(ws: &mut S) -> Result<TurnOutcome, OrchestratorError>
|
||||||
where
|
where
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ mod tools;
|
|||||||
|
|
||||||
pub use events::{RunEventBody, RunEventEnvelope};
|
pub use events::{RunEventBody, RunEventEnvelope};
|
||||||
pub use outbox::{drain_once, spawn_drainer, EmailSender, LettreSender, SmtpConfig};
|
pub use outbox::{drain_once, spawn_drainer, EmailSender, LettreSender, SmtpConfig};
|
||||||
pub use runtime::{ProviderRegistry, Runtime, RuntimeConfig, RuntimeError, StartedRun};
|
pub use runtime::{judge_model, ProviderRegistry, Runtime, RuntimeConfig, RuntimeError, StartedRun};
|
||||||
pub use sandboxes::SandboxManager;
|
pub use sandboxes::SandboxManager;
|
||||||
pub use tools::{ClockNow, EmailSend, Tool, ToolContext, ToolRegistry};
|
pub use tools::{ClockNow, EmailSend, Tool, ToolContext, ToolRegistry};
|
||||||
|
|||||||
Reference in New Issue
Block a user