Watch
1
0
Fork
You've already forked souveraine
0

agent: per-agent voice_id on the public list

AgentSummary carries voice_id, sourced from agent.json (_souveraine) via
get() rather than the DB config_json column, which is write-once at create
and drifts on later edits. The list endpoint is the surface's only
unauthenticated view of an agent, so voice travels there; /v1/agents/:id
is token-gated.
This commit is contained in:
Fimeg 2026-07-30 09:18:38 -04:00
commit e9bf33e64a
2 changed files with 40 additions and 1 deletions

View file

@ -10,6 +10,16 @@ pub struct AgentSummary {
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub tags: Vec<String>,
/// This agent's own voice (a TTS voice name registered on the box), if set.
/// None means "sound like the substrate" — fall back to the system voice.
///
/// Sourced from `agent.json` (the `_souveraine` block) via `get()`, not the
/// DB's `config_json` column, because that column is write-once at create
/// and goes stale on a later agent.json edit. The public list endpoint is
/// the surface's only unauthenticated view of an agent, so voice travels
/// here — `/v1/agents/:id` (the full state) is token-gated.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub voice_id: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -111,6 +121,18 @@ pub struct SouveraineConfig {
/// `[inference] provider`. None falls back to the global default.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub provider: Option<String>,
/// Per-agent voice — how *this* agent sounds, independent of the substrate.
///
/// `[voice] voice_id` is the **system** voice: the substrate speaking as
/// itself. It is not a statement about who any agent is. Two agents on one
/// host should be able to sound like themselves, so the agent's own voice
/// lives here and wins when set; None falls back to the system voice.
///
/// The name is whatever the TTS service has registered (`GET
/// /audio/voices`); an unknown name falls back service-side rather than
/// failing, so a stale value degrades to the system voice.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub voice_id: Option<String>,
}
#[derive(Debug, Deserialize)]