Watch
0
0
Fork
You've already forked hyperhive
0

swarm: per-agent inference settings (model, effort, subagent_models) in KV

swarm-controller keeps each agent's inference settings in a new
`agent-inference` KV bucket, one key per agent, and is its only writer
(`GET`/`PUT`/`DELETE /api/agents/{name}/inference`; `swarmctl agent
inference get|set|clear`). Every field is optional. Each agent reads its
own key every 10 s through a direct-get grant on that key alone, and a
set `model` or `effort` replaces the Bus value, so the next turn runs on
it and the badge follows.

The swarm value is applied without persisting it: `Bus::set_model` and
`set_effort` are split into a persisting setter and a non-persisting
`apply_*`, and the poller uses the latter. Otherwise the swarm value
would overwrite `hyperhive-model`/`hyperhive-effort`, and clearing it, or
a restart, would no longer find the agent's own value. An unset field
changes nothing; a field cleared after being applied goes back to the
local value (`harness_state::local_model`/`local_effort`, the same
resolution `Bus::new` uses), read again at the clear.

`subagent_models` is validated, stored and shown by `get`; no agent
applies it yet.

Refs #5034
This commit is contained in:
atlas 2026-10-09 23:11:58 +02:00
commit 916fdb35b8
24 changed files with 1432 additions and 34 deletions

View file

@ -29,6 +29,7 @@
mod agent;
mod forge;
mod inference;
mod schedule;
mod users;
@ -210,6 +211,55 @@ enum AgentVerb {
/// Queues and returns, the same way `agent create` does — watch the
/// swarm UI's job view for the outcome.
MintForgeToken(AgentMintForgeTokenArgs),
/// Show or change the model, effort and subagent models the swarm sets
/// for an agent.
///
/// A field the swarm sets wins over the agent's own value (from its
/// `/model` or `/effort` pick or its agent.nix) from its next turn on;
/// the agent reads its settings every ten seconds. A field the swarm
/// doesn't set, or clears, leaves the agent on its own value.
Inference {
#[command(subcommand)]
command: InferenceVerb,
},
}
#[derive(Subcommand)]
enum InferenceVerb {
/// Show what the swarm sets for an agent, naming the fields it doesn't
/// set.
Get(InferenceAgentArgs),
/// Set fields for an agent. Only the flags given change; the others keep
/// what's stored.
Set(InferenceSetArgs),
/// Clear every field for an agent, so it goes back to its own values.
Clear(InferenceAgentArgs),
}
#[derive(Args)]
struct InferenceAgentArgs {
/// Agent name.
agent: String,
#[command(flatten)]
socket: ControllerSocketArg,
}
#[derive(Args)]
struct InferenceSetArgs {
/// Agent name. A hive must declare it.
agent: String,
/// The model its turns run on, as claude's `--model` takes it.
#[arg(long, value_name = "MODEL")]
model: Option<String>,
/// The reasoning effort its turns run at.
#[arg(long, value_name = "LEVEL", value_parser = ["low", "medium", "high", "xhigh", "max"])]
effort: Option<String>,
/// The models it may start subagents on, comma-separated. Stored and
/// shown; the agent doesn't apply it yet.
#[arg(long, value_name = "MODELS", value_delimiter = ',')]
subagent_models: Option<Vec<String>>,
#[command(flatten)]
socket: ControllerSocketArg,
}
#[derive(Args)]
@ -496,6 +546,9 @@ fn main() -> Result<()> {
let socket = path_from(args.controller_socket, "SWARM_CONTROLLER_SOCKET")?;
agent::mint_forge_token(&socket, &args.name)
}
Verb::Agent {
command: AgentVerb::Inference { command },
} => inference(command),
// Same socket-resolution reasoning as `Create` above.
Verb::Forge {
command: ForgeVerb::MakeAdmin(args),
@ -544,6 +597,22 @@ fn main() -> Result<()> {
}
}
fn inference(command: InferenceVerb) -> Result<()> {
match command {
InferenceVerb::Get(a) => inference::get(&a.socket.resolve()?, &a.agent),
InferenceVerb::Set(a) => inference::set(
&a.socket.resolve()?,
&a.agent,
inference::SetFlags {
model: a.model,
effort: a.effort,
subagent_models: a.subagent_models,
},
),
InferenceVerb::Clear(a) => inference::clear(&a.socket.resolve()?, &a.agent),
}
}
fn schedule(command: ScheduleVerb) -> Result<()> {
match command {
ScheduleVerb::Add(a) => schedule::add(