Struct Config
pub struct Config {Show 100 fields
pub data_dir: PathBuf,
pub config_path: PathBuf,
pub env_overridden_paths: HashSet<String>,
pub pre_override_snapshots: HashMap<String, String>,
pub onepassword_reference_snapshots: HashMap<String, String>,
pub dirty_paths: HashSet<String>,
pub degraded_security: Vec<String>,
pub degraded_sections: Vec<String>,
pub retired_wati_config_sections: Vec<String>,
pub retired_node_transport_config: bool,
pub loaded_from: Option<PathBuf>,
pub schema_version: u32,
pub providers: Providers,
pub model_routes: Vec<ModelRouteConfig>,
pub embedding_routes: Vec<EmbeddingRouteConfig>,
pub observability: ObservabilityConfig,
pub trust: TrustConfig,
pub security: SecurityConfig,
pub tools: BuiltinToolsConfig,
pub backup: BackupConfig,
pub data_retention: DataRetentionConfig,
pub cloud_ops: CloudOpsConfig,
pub conversational_ai: ConversationalAiConfig,
pub security_ops: SecurityOpsConfig,
pub runtime: RuntimeConfig,
pub reliability: ReliabilityConfig,
pub scheduler: SchedulerConfig,
pub eval: EvalHarnessConfig,
pub pacing: PacingConfig,
pub skills: SkillsConfig,
pub pipeline: PipelineConfig,
pub query_classification: QueryClassificationConfig,
pub heartbeat: HeartbeatConfig,
pub cron: HashMap<String, CronJobDecl>,
pub acp: AcpConfig,
pub channels: ChannelsConfig,
pub memory: MemoryConfig,
pub storage: StorageConfig,
pub tunnel: TunnelConfig,
pub gateway: GatewayConfig,
pub a2a: A2aServerSection,
pub wss: WssConfig,
pub rpc: RpcConfig,
pub relay: RelayConfig,
pub enroll: EnrollConfig,
pub composio: ComposioConfig,
pub microsoft365: Microsoft365Config,
pub secrets: SecretsConfig,
pub browser: BrowserConfig,
pub browser_delegate: BrowserDelegateConfig,
pub http_request: HttpRequestConfig,
pub multimodal: MultimodalConfig,
pub media_pipeline: MediaPipelineConfig,
pub web_fetch: WebFetchConfig,
pub link_enricher: LinkEnricherConfig,
pub text_browser: TextBrowserConfig,
pub web_search: WebSearchConfig,
pub project_intel: ProjectIntelConfig,
pub google_workspace: GoogleWorkspaceConfig,
pub proxy: ProxyConfig,
pub cost: CostConfig,
pub peripherals: PeripheralsConfig,
pub delegate: DelegateToolConfig,
pub agents: HashMap<String, AliasedAgentConfig>,
pub risk_profiles: HashMap<String, RiskProfileConfig>,
pub decision_models: HashMap<String, SopDecisionModelConfig>,
pub oidc: HashMap<String, OidcConfig>,
pub users: HashMap<String, UserConfig>,
pub permission_profiles: HashMap<String, PermissionProfileConfig>,
pub runtime_profiles: HashMap<String, RuntimeProfileConfig>,
pub skill_bundles: HashMap<String, SkillBundleConfig>,
pub knowledge_bundles: HashMap<String, KnowledgeBundleConfig>,
pub mcp_bundles: HashMap<String, McpBundleConfig>,
pub peer_groups: HashMap<String, PeerGroupConfig>,
pub hooks: HooksConfig,
pub hardware: HardwareConfig,
pub transcription: TranscriptionConfig,
pub tts: TtsConfig,
pub mcp: McpConfig,
pub nodes: NodesConfig,
pub onboard_state: OnboardStateConfig,
pub notion: NotionConfig,
pub jira: JiraConfig,
pub knowledge: KnowledgeConfig,
pub linkedin: LinkedInConfig,
pub image_gen: ImageGenConfig,
pub file_upload: FileUploadConfig,
pub file_upload_bundle: FileUploadBundleConfig,
pub file_download: FileDownloadConfig,
pub plugins: PluginsConfig,
pub locale: Option<String>,
pub verifiable_intent: VerifiableIntentConfig,
pub claude_code: ClaudeCodeConfig,
pub claude_code_runner: ClaudeCodeRunnerConfig,
pub codex_cli: CodexCliConfig,
pub gemini_cli: GeminiCliConfig,
pub opencode_cli: OpenCodeCliConfig,
pub sop: SopConfig,
pub shell_tool: ShellToolConfig,
pub escalation: EscalationConfig,
}Expand description
Top-level ZeroClaw configuration, loaded from config.toml.
Resolution order: ZEROCLAW_CONFIG_DIR env → ZEROCLAW_WORKSPACE env → ~/.zeroclaw/config.toml.
Fields§
§data_dir: PathBufShared instance data directory (databases, hygiene state, cost
records, daemon state files). Computed from ZEROCLAW_CONFIG_DIR
/ ZEROCLAW_DATA_DIR / ZEROCLAW_WORKSPACE (deprecated) at
load time, not serialized. Per-agent identity + markdown lives
at agent_workspace_dir(&alias), not here.
config_path: PathBufPath to config.toml - computed from home, not serialized
env_overridden_paths: HashSet<String>Dotted prop-paths overridden by ZEROCLAW_* env vars at load time.
Populated by apply_env_overrides; consulted by save() to mask the
env-injected values back to disk-or-default before encryption, and by
prop_is_env_overridden for O(1) display-layer lookup (config list,
dashboard, quickstart).
pre_override_snapshots: HashMap<String, String>Per-path snapshot of pre-override raw values, captured at apply time
from the post-decrypt_secrets in-memory state (so secret entries
hold plaintext, not the display mask). save() restores from this
map so env-injected values never reach disk and the operator’s
original on-disk credentials survive any save cycle.
onepassword_reference_snapshots: HashMap<String, String>Per-path snapshot of op:// external secret references captured before
decrypt_secrets() resolves them for runtime use. save() restores
these references unless the same path was intentionally edited.
dirty_paths: HashSet<String>Dotted prop-paths mutated since the last persist; drives the
per-path PATCH applied by save_dirty().
degraded_security: Vec<String>Security-critical sections the resilient loader reset to Default
because the on-disk block was malformed. Non-empty = posture may be
weaker than intended; exposure gating should refuse to trust the
instance until repaired. Never serialized — a load-time signal.
degraded_sections: Vec<String>Non-security sections the resilient loader reset to Default
because the on-disk block was malformed (e.g. [plugins.entries]
written where [[plugins.entries]] was meant). Never serialized;
a load-time signal the CLI surfaces on stderr so a silently-dropped
section is impossible to miss.
retired_wati_config_sections: Vec<String>Retired WATI config section roots detected before migration and typed deserialization erase them. Never serialized; the CLI surfaces each path on stderr so an operator cannot miss the retired channel.
retired_node_transport_config: boolWhether a retired [node_transport] section was present before
migration and typed deserialization erased it. Never serialized; the
CLI surfaces upgrade guidance without retaining the retired secret.
loaded_from: Option<PathBuf>The config file this value was populated from — set by
load_or_init (both the existing-file read and the fresh-init
write) and by loaders that re-read a config file before mutating.
Default/programmatic construction leaves it None, and save()
then refuses to overwrite an existing file this value cannot prove
it read, so a near-empty snapshot cannot wipe an operator’s config;
force_save() is the explicit intentional-overwrite path. Binding
provenance to the path (not a boolean) also refuses a value loaded
from file A that is later repointed at a different existing file B.
Never serialized — a load-time signal.
schema_version: u32Config file schema version.
providers: ProvidersAll configured provider profiles, grouped by category under a
single [providers] root. Categories today: models, tts,
transcription. Shape: [providers.<category>.<type>.<alias>],
e.g. [providers.models.anthropic.default],
[providers.tts.openai.default],
[providers.transcription.groq.default].
model_routes: Vec<ModelRouteConfig>Model-routing rules — route hint:<name> to specific
model_provider + model combos.
embedding_routes: Vec<EmbeddingRouteConfig>Embedding-routing rules — route hint:<name> to specific
model_provider + model combos for embedding requests.
observability: ObservabilityConfigObservability backend configuration ([observability]).
trust: TrustConfigTrust scoring and regression detection configuration ([trust]).
security: SecurityConfigSecurity subsystem configuration ([security]).
tools: BuiltinToolsConfigOptional model-visible built-ins ([tools]). The default is full;
optional = [] selects the eleven core tools. Selection never grants
execution permission. Reload after edits.
backup: BackupConfigBackup tool configuration ([backup]).
data_retention: DataRetentionConfigData retention and purge configuration ([data_retention]).
cloud_ops: CloudOpsConfigCloud transformation accelerator configuration ([cloud_ops]).
conversational_ai: ConversationalAiConfigConversational AI agent builder configuration ([conversational_ai]).
Experimental / future feature — not yet wired into the agent runtime.
Omitted from generated config files when disabled (the default).
Existing configs that already contain this section will continue to
deserialize correctly thanks to #[serde(default)].
security_ops: SecurityOpsConfigManaged cybersecurity service configuration ([security_ops]).
runtime: RuntimeConfigRuntime adapter configuration ([runtime]). Controls native vs Docker execution.
reliability: ReliabilityConfigReliability settings: retries, backoff, key rotation ([reliability]).
scheduler: SchedulerConfigScheduler configuration for periodic task execution ([scheduler]).
eval: EvalHarnessConfigAgent evaluation harness ([eval]) — surfaced via zeroclaw eval.
Distinct from [agent.eval], which is the in-loop response-quality scorer.
pacing: PacingConfigPacing controls for slow/local LLM workloads ([pacing]).
skills: SkillsConfigSkills loading and community repository behavior ([skills]).
pipeline: PipelineConfigPipeline tool configuration ([pipeline]).
query_classification: QueryClassificationConfigAutomatic query classification — maps user messages to model hints.
heartbeat: HeartbeatConfigHeartbeat configuration for periodic health pings ([heartbeat]).
cron: HashMap<String, CronJobDecl>Declarative cron jobs ([cron.<alias>]), alias-keyed.
Each entry is a named scheduled job synced into the database at
scheduler startup. Subsystem runtime knobs (enable/disable, catch-up,
run-history retention) live on [scheduler].
acp: AcpConfigACP (Agent Client Protocol) server configuration ([acp]).
channels: ChannelsConfigChannel configurations: Telegram, Discord, Slack, etc. ([channels]).
memory: MemoryConfigMemory backend configuration: sqlite, markdown, embeddings ([memory]).
storage: StorageConfigPersistent storage model_provider configuration ([storage]).
tunnel: TunnelConfigTunnel configuration for exposing the gateway publicly ([tunnel]).
gateway: GatewayConfigGateway server configuration: host, port, pairing, rate limits ([gateway]).
a2a: A2aServerSectionInbound A2A discovery server ([a2a.server]). Default-closed:
serves the well-known catalog card and per-alias agent cards only
when enabled = true. See crate::multi_agent::A2aServerConfig.
wss: WssConfigWebSocket Secure (WSS) transport for remote TUI connections ([wss]).
rpc: RpcConfigLocal IPC endpoint limits for the RPC socket or named pipe ([rpc]).
relay: RelayConfigNominated-relay client for reaching this daemon through a relay ([relay]).
enroll: EnrollConfigCertificate enrollment endpoint for certless clients ([enroll]).
composio: ComposioConfigComposio managed OAuth tools integration ([composio]).
microsoft365: Microsoft365ConfigMicrosoft 365 Graph API integration ([microsoft365]).
secrets: SecretsConfigSecrets encryption configuration ([secrets]).
browser: BrowserConfigBrowser automation configuration ([browser]).
browser_delegate: BrowserDelegateConfigBrowser delegation configuration ([browser_delegate]).
Delegates browser-based tasks to a browser-capable CLI subprocess (e.g.
Claude Code with claude-in-chrome MCP tools). Useful for interacting
with corporate web apps (Teams, Outlook, Jira, Confluence) that lack
direct API access. A persistent Chrome profile can be configured so SSO
sessions survive across invocations.
Fields:
enabled(bool, defaultfalse) — enable the browser delegation tool.cli_binary(String, default"claude") — CLI binary to spawn for browser tasks.chrome_profile_dir(String, default"") — Chrome user-data directory for persistent SSO sessions. When empty, a fresh profile is used each invocation.allowed_domains(Vec<String>, default[]) — allowlist of domains the browser may navigate to. Empty means all non-blocked domains are permitted.blocked_domains(Vec<String>, default[]) — denylist of domains. Blocked domains take precedence over allowed domains.task_timeout_secs(u64, default120) — per-task timeout in seconds.
Compatibility: additive and disabled by default; existing configs remain valid when omitted.
Rollback/migration: remove [browser_delegate] or keep enabled = false to disable.
http_request: HttpRequestConfigHTTP request tool configuration ([http_request]).
multimodal: MultimodalConfigMultimodal (image) handling configuration ([multimodal]).
media_pipeline: MediaPipelineConfigAutomatic media understanding pipeline ([media_pipeline]).
web_fetch: WebFetchConfigWeb fetch tool configuration ([web_fetch]).
link_enricher: LinkEnricherConfigLink enricher configuration ([link_enricher]).
text_browser: TextBrowserConfigText browser tool configuration ([text_browser]).
web_search: WebSearchConfigWeb search tool configuration ([web_search]).
project_intel: ProjectIntelConfigProject delivery intelligence configuration ([project_intel]).
google_workspace: GoogleWorkspaceConfigGoogle Workspace CLI (gws) tool configuration ([google_workspace]).
proxy: ProxyConfigProxy configuration for outbound HTTP/HTTPS/SOCKS5 traffic ([proxy]).
cost: CostConfigCost tracking and budget enforcement configuration ([cost]).
Also hosts the operator-managed rate sheet at
[cost.rates.<type>.<model>].
peripherals: PeripheralsConfigPeripheral board configuration for hardware integration ([peripherals]).
delegate: DelegateToolConfigDelegate tool global default configuration ([delegate]).
agents: HashMap<String, AliasedAgentConfig>Aliased agents in this install. Each entry under [agents.<alias>]
is one user-facing agent with its own identity, channels, model
provider, risk profile, workspace, and memory scope.
DelegateTool consults this map when one agent delegates a
subtask to another.
risk_profiles: HashMap<String, RiskProfileConfig>Named risk/autonomy profiles ([risk_profiles.<alias>]).
decision_models: HashMap<String, SopDecisionModelConfig>Named typed-decision models ([decision_models.<alias>]): TypeSafe Jev,
a self-hosted Laya, or any custom System One endpoint. An SOP selects
one by alias in its [decision] model field; an alias that is not
configured makes that SOP dispatch fail-closed.
oidc: HashMap<String, OidcConfig>OIDC trust relationships ([oidc.<alias>]). Each entry names one
issuer whose identities this daemon accepts and how their verified
claims map to permission profiles. Any standards-compliant IdP
works; there is no per-vendor configuration.
users: HashMap<String, UserConfig>Local user roster ([users.<name>]) for credential-to-principal
mapping of local auth providers (peer credentials today). OIDC
identities are NOT listed here; they are keyed by issuer + subject.
permission_profiles: HashMap<String, PermissionProfileConfig>Named permission profiles ([permission_profiles.<alias>]): the
single runtime authorization vocabulary. OIDC claim mappings and
user roster entries resolve here; deny-by-default: anything a
profile does not grant is refused.
runtime_profiles: HashMap<String, RuntimeProfileConfig>Named runtime/LLM execution profiles ([runtime_profiles.<alias>]).
skill_bundles: HashMap<String, SkillBundleConfig>Named skill bundles ([skill_bundles.<alias>]).
knowledge_bundles: HashMap<String, KnowledgeBundleConfig>Named knowledge bundles ([knowledge_bundles.<alias>]).
mcp_bundles: HashMap<String, McpBundleConfig>Named MCP server bundles ([mcp_bundles.<alias>]).
peer_groups: HashMap<String, PeerGroupConfig>Named peer groups ([peer_groups.<name>]). Each entry binds a
channel, a list of member agents, and optional non-agent
(external) members and a per-group blocklist. Mutual opt-in:
two agents become peers only when both appear in the same
group’s agents. Empty by default for single-agent installs.
See crate::multi_agent::PeerGroupConfig.
hooks: HooksConfigHooks configuration (lifecycle hooks and built-in hook toggles).
hardware: HardwareConfigHardware configuration (wizard-driven physical world setup).
transcription: TranscriptionConfigVoice transcription configuration (Whisper API via Groq).
tts: TtsConfigText-to-Speech configuration ([tts]).
mcp: McpConfigExternal MCP server connections ([mcp]).
nodes: NodesConfigDynamic node discovery configuration ([nodes]).
onboard_state: OnboardStateConfigMeta-state for the Quickstart flow (which sections the user has
already walked through). Not user-facing config ([onboard_state]).
notion: NotionConfigNotion integration configuration ([notion]).
jira: JiraConfigJira integration configuration ([jira]).
knowledge: KnowledgeConfigKnowledge graph configuration ([knowledge]).
linkedin: LinkedInConfigLinkedIn integration configuration ([linkedin]).
image_gen: ImageGenConfigStandalone image generation tool configuration ([image_gen]).
file_upload: FileUploadConfigStandalone file upload tool configuration ([file_upload]).
file_upload_bundle: FileUploadBundleConfigStandalone multi-file bundle upload tool configuration
([file_upload_bundle]).
file_download: FileDownloadConfigStandalone file download tool configuration ([file_download]).
plugins: PluginsConfigPlugin system configuration ([plugins]).
locale: Option<String>Locale for tool descriptions (e.g. "en", "zh-CN").
When set, tool descriptions shown in system prompts are loaded from
Fluent .ftl locale files. Falls back to embedded English, then to
hardcoded descriptions.
If omitted or empty, the locale is auto-detected from the host
system’s locale (defaulting to "en" if that can’t be determined).
verifiable_intent: VerifiableIntentConfigVerifiable Intent (VI) credential issuance and constraint checking
([verifiable_intent]). No credential chain verifier exists yet, so the
vi_verify tool is not registered for the model and this section does not
currently enable verification of anything.
claude_code: ClaudeCodeConfigClaude Code tool configuration ([claude_code]).
claude_code_runner: ClaudeCodeRunnerConfigClaude Code task runner with Slack progress and SSH session handoff ([claude_code_runner]).
codex_cli: CodexCliConfigCodex CLI tool configuration ([codex_cli]).
gemini_cli: GeminiCliConfigGemini CLI tool configuration ([gemini_cli]).
opencode_cli: OpenCodeCliConfigOpenCode CLI tool configuration ([opencode_cli]).
sop: SopConfigStandard Operating Procedures engine configuration ([sop]).
shell_tool: ShellToolConfigShell tool configuration ([shell_tool]).
escalation: EscalationConfigEscalation routing configuration ([escalation]).
Implementations§
Source§impl Config
impl Config
Sourcepub fn configurable_prefix() -> &'static str
pub fn configurable_prefix() -> &'static str
Returns the #[prefix] value for this Configurable struct.
Sourcepub fn init_requires_explicit_config() -> bool
pub fn init_requires_explicit_config() -> bool
True when this struct has a required leaf field that a
bare/ancestor-prefix init_defaults scaffold must not
materialize (it would fill the field with its Rust
Default, which prune_empty_leaves then strips on save,
leaving a partial sub-table that fails strict reload).
Explicitly targeting this section (or a descendant of it)
still scaffolds regardless of this flag, so the section can
be materialized for the operator to fill in.
Sourcepub fn secret_fields(&self) -> Vec<SecretFieldInfo>
pub fn secret_fields(&self) -> Vec<SecretFieldInfo>
Returns metadata about all #[secret] fields on this struct and nested children.
pub fn secret_field_terminals() -> Vec<&'static str>
Sourcepub fn encrypt_secrets(&mut self, store: &SecretStore) -> Result<()>
pub fn encrypt_secrets(&mut self, store: &SecretStore) -> Result<()>
Encrypt all secret fields in place using the provided store.
Sourcepub fn decrypt_secrets(&mut self, store: &SecretStore) -> Result<()>
pub fn decrypt_secrets(&mut self, store: &SecretStore) -> Result<()>
Decrypt all secret fields in place using the provided store.
Sourcepub fn set_secret(&mut self, name: &str, value: String) -> Result<()>
pub fn set_secret(&mut self, name: &str, value: String) -> Result<()>
Set a secret field by its full dotted name, dispatching to nested children.
Sourcepub fn prop_fields(&self) -> Vec<PropFieldInfo>
pub fn prop_fields(&self) -> Vec<PropFieldInfo>
Returns metadata about all property fields on this struct and nested children.
Sourcepub fn get_prop(&self, name: &str) -> Result<String>
pub fn get_prop(&self, name: &str) -> Result<String>
Get a property value by its full dotted name, returning it as a display string.
Sourcepub fn set_prop(&mut self, name: &str, value_str: &str) -> Result<()>
pub fn set_prop(&mut self, name: &str, value_str: &str) -> Result<()>
Set a property value by its full dotted name, parsing from string.
Sourcepub fn prop_is_secret(name: &str) -> bool
pub fn prop_is_secret(name: &str) -> bool
Check if a property name refers to a secret field (static, no instance needed).
Sourcepub fn init_defaults(&mut self, prefix: Option<&str>) -> Vec<&'static str>
pub fn init_defaults(&mut self, prefix: Option<&str>) -> Vec<&'static str>
Instantiate None nested sections whose prefix matches.
Returns the prefixes that were initialized.
Sourcepub fn map_key_sections() -> Vec<MapKeySection>
pub fn map_key_sections() -> Vec<MapKeySection>
Enumerate every map-keyed (HashMap<String, T>) and list-shaped
(Vec<T>) section discoverable from this Configurable’s tree.
The dashboard / CLI consume this to surface “+ Add” affordances
without hardcoding the section list.
Sourcepub fn nested_section_help(name: &str) -> Option<&'static str>
pub fn nested_section_help(name: &str) -> Option<&'static str>
Help blurb for a #[nested] field on this struct, sourced from
the field-level /// docstring. Returns None for unknown
names so callers can fall through to a different lookup.
pub fn nested_section_group(name: &str) -> Option<&'static str>
Sourcepub fn get_map_keys(&self, section_path: &str) -> Option<Vec<String>>
pub fn get_map_keys(&self, section_path: &str) -> Option<Vec<String>>
Return the current alias keys at section_path, or None if
the path doesn’t resolve to a map-keyed section in this tree.
pub fn nested_option_entries(&self) -> Vec<NestedOptionEntry>
pub fn create_map_key( &mut self, section_path: &str, map_key: &str, ) -> Result<bool, String>
pub fn delete_map_key( &mut self, section_path: &str, map_key: &str, ) -> Result<bool, String>
pub fn rename_map_key( &mut self, section_path: &str, map_key: &str, new_key: &str, ) -> Result<bool, String>
Source§impl Config
impl Config
Sourcepub fn resolve_alias_source(&self, source: AliasSource) -> Vec<String>
pub fn resolve_alias_source(&self, source: AliasSource) -> Vec<String>
Resolve the configured alias values valid for an crate::traits::AliasSource.
Two-tier sources return dotted <type>.<alias> keys; flat sources
return bare alias keys. The single resolver every surface uses for
PropKind::AliasRef pickers and validation.
Sourcepub fn resolve_default_model(&self) -> Option<String>
pub fn resolve_default_model(&self) -> Option<String>
Return the first concrete model string available for use as a
default: the model declared by the first entry that has one. Entries
are visited in macro slot order, then sorted alias order within each
slot, as implemented by
ModelProviders::first_entry_with_model.
Returns None only when no model-provider entry has any model
configured at all.
Sourcepub fn risk_profile_for_agent(
&self,
agent_alias: &str,
) -> Option<&RiskProfileConfig>
pub fn risk_profile_for_agent( &self, agent_alias: &str, ) -> Option<&RiskProfileConfig>
Resolve the risk profile for an explicit agent alias.
Each agent’s risk_profile field names a [risk_profiles.<alias>]
entry that gates its actions. There is no “global” risk profile in
every callsite must come through an agent. When the agent has
no profile set or names a missing entry, returns None and the
caller decides how to handle it (validation rejects this shape at
load time; the runtime treating None as a config error).
Sourcepub fn reachable_delegate_target_configs(
&self,
caller_alias: &str,
) -> Vec<DelegateTargetConfig>
pub fn reachable_delegate_target_configs( &self, caller_alias: &str, ) -> Vec<DelegateTargetConfig>
Resolve the delegate targets caller_alias may reach:
same-profile peers when delegate_same_risk_profile is set, unioned
with the explicit delegates roster, minus the caller. Single
source of truth for delegate reach and mode; gating
(delegation_policy) is enforced separately by the caller.
Deduped, sorted; unknown caller yields empty. Disabled targets are
never reachable. Explicit entries override the bounded mode used for
implicit same-profile peers.
Sourcepub fn reachable_delegate_targets(&self, caller_alias: &str) -> Vec<String>
pub fn reachable_delegate_targets(&self, caller_alias: &str) -> Vec<String>
Resolve only the agent aliases reachable by caller_alias.
Use Self::reachable_delegate_target_configs when the target mode
matters.
Sourcepub fn delegate_target_mode(
&self,
caller_alias: &str,
target_alias: &str,
) -> Option<DelegateExecutionMode>
pub fn delegate_target_mode( &self, caller_alias: &str, target_alias: &str, ) -> Option<DelegateExecutionMode>
Resolve the execution mode for one reachable delegate target.
Target aliases are normalized the same way the reachable roster
normalizes explicit delegates entries. This keeps callers that need
one target mode aligned with the canonical roster resolver instead of
creating a subtly different admission rule.
Sourcepub fn runtime_profile_for_agent(
&self,
agent_alias: &str,
) -> Option<&RuntimeProfileConfig>
pub fn runtime_profile_for_agent( &self, agent_alias: &str, ) -> Option<&RuntimeProfileConfig>
Resolve the [runtime_profiles.<alias>] entry owned by an agent
(via agents.<alias>.runtime_profile). Returns None when the
agent has no runtime profile set or names a missing entry. Unlike
risk_profile_for_agent, the missing case is not a hard error
because runtime budgets and tunables fall back to global defaults.
Sourcepub fn effective_summary_provider(
&self,
agent_alias: &str,
) -> Option<ModelProviderRef>
pub fn effective_summary_provider( &self, agent_alias: &str, ) -> Option<ModelProviderRef>
Effective context-compression summarizer provider for an agent:
agent-level summary_provider override → the runtime profile’s
context_compression.summary_provider → None (the caller then reuses
the agent’s own provider+model, optionally via the deprecated
summary_model swap). Unlike the inert agent-inline tunables below, the
agent-level override IS consulted — it’s an explicit per-agent choice,
mirroring classifier_provider’s “empty = inherit” semantics.
pub fn effective_max_tool_iterations(&self, agent_alias: &str) -> usize
pub fn effective_single_tool_rounds(&self, agent_alias: &str) -> bool
pub fn effective_max_execution_tree_iterations( &self, agent_alias: &str, ) -> Option<usize>
pub fn effective_max_history_messages(&self, agent_alias: &str) -> usize
Sourcepub fn effective_structured_max_history_messages(
&self,
agent_alias: &str,
) -> usize
pub fn effective_structured_max_history_messages( &self, agent_alias: &str, ) -> usize
Resolve the whole-turn history cap used by structured Agent sessions.
The legacy config key is named max_history_messages, but structured
Agent sessions enforce it at complete user-turn boundaries. Tool-call
and tool-result rows therefore do not consume independent slots there.
pub fn effective_max_context_tokens(&self, agent_alias: &str) -> Option<usize>
Sourcepub fn effective_context_compact_ratio(&self, agent_alias: &str) -> Option<f64>
pub fn effective_context_compact_ratio(&self, agent_alias: &str) -> Option<f64>
Optional fraction of the selected model’s context window at which proactive trimming fires. Invalid values are treated as unset so they cannot silently opt an existing profile into model-relative budgeting.
Sourcepub fn configured_model_context_window(
&self,
agent_alias: &str,
) -> Option<usize>
pub fn configured_model_context_window( &self, agent_alias: &str, ) -> Option<usize>
The model’s context window exactly as configured, or None when no
provider profile declares one.
None means unknown, not “small”. Report it to an operator as unset
rather than resolving it to UNCONFIGURED_CONTEXT_WINDOW_FALLBACK,
which would present a stub as though it were the model’s real capacity.
Use Config::effective_model_context_window when a number is required
for budget arithmetic.
Sourcepub fn effective_model_context_window(&self, agent_alias: &str) -> usize
pub fn effective_model_context_window(&self, agent_alias: &str) -> usize
Returns the model’s context window size (max input tokens).
Source: provider config context_window →
UNCONFIGURED_CONTEXT_WINDOW_FALLBACK.
Does NOT check runtime profile (that’s for output budget).
Sourcepub fn resolved_model_context_window(
&self,
agent_alias: &str,
) -> ResolvedModelContextWindow
pub fn resolved_model_context_window( &self, agent_alias: &str, ) -> ResolvedModelContextWindow
Resolve model capacity and its provenance for an agent’s configured route. Unknown agents and unconfigured capacities retain the numeric compatibility fallback while remaining explicitly identifiable.
Sourcepub fn effective_model_context_window_for_route(
&self,
model_provider_ref: &str,
selected_model: &str,
) -> usize
pub fn effective_model_context_window_for_route( &self, model_provider_ref: &str, selected_model: &str, ) -> usize
Resolve model capacity for the provider alias and model selected for a
turn. context_window describes the model configured on that alias; a
different per-session model override therefore falls back to the legacy
unknown-capacity value instead of borrowing metadata for another model.
Sourcepub fn resolved_model_context_window_for_route(
&self,
model_provider_ref: &str,
selected_model: &str,
) -> ResolvedModelContextWindow
pub fn resolved_model_context_window_for_route( &self, model_provider_ref: &str, selected_model: &str, ) -> ResolvedModelContextWindow
Resolve capacity for exactly the selected provider profile and model.
A model mismatch or missing positive context_window is an explicit
compatibility fallback, never borrowed metadata from another model.
Sourcepub fn resolved_context_limits_for_route(
&self,
agent_alias: &str,
model_provider_ref: &str,
selected_model: &str,
) -> ResolvedContextLimits
pub fn resolved_context_limits_for_route( &self, agent_alias: &str, model_provider_ref: &str, selected_model: &str, ) -> ResolvedContextLimits
Resolve one route’s capacity and proactive budget from their canonical owners: the selected provider alias/model and the agent runtime profile.
Sourcepub fn model_provider_context_window_opt(
&self,
provider_ref: &str,
model: &str,
) -> Option<usize>
pub fn model_provider_context_window_opt( &self, provider_ref: &str, model: &str, ) -> Option<usize>
Provider’s explicit context_window for the served model, or None.
Use on wire boundaries: emitting the 32k stub from
effective_model_context_window() would freeze the client
meter at 32k instead of the profile budget. Use this instead
of the agent-alias variant when the live provider identity is
known (e.g., from Agent.attribution_fields().1 or
SessionOverrides.model_provider). Returns None when the
ref is unparseable, the entry has no context_window, or the
served model does not match the entry’s configured primary
model, so the wire omission path preserves absence (no 32k
stub leak) and fallback/vision/override models never borrow
another model’s capacity.
pub fn effective_memory_recall_limit(&self, agent_alias: &str) -> usize
pub fn effective_compact_context(&self, agent_alias: &str) -> bool
pub fn effective_parallel_tools(&self, agent_alias: &str) -> bool
pub fn effective_tool_dispatcher(&self, agent_alias: &str) -> String
pub fn effective_tool_call_dedup_exempt(&self, agent_alias: &str) -> Vec<String>
pub fn effective_max_system_prompt_chars(&self, agent_alias: &str) -> usize
pub fn effective_max_tool_result_chars(&self, agent_alias: &str) -> usize
pub fn effective_keep_tool_context_turns(&self, agent_alias: &str) -> usize
Sourcepub fn resolved_agent_config(
&self,
agent_alias: &str,
) -> Option<AliasedAgentConfig>
pub fn resolved_agent_config( &self, agent_alias: &str, ) -> Option<AliasedAgentConfig>
Return a clone of the named agent’s AliasedAgentConfig with all
runtime-profile overrides baked in. Use this when an Agent (or
any other struct) needs to own a self-contained, already-resolved
view of the agent’s runtime knobs without holding a reference to
the full Config.
Returns None when agent_alias is not present in agents.
Semantics: every field touched here mirrors the matching
effective_* helper above. If you add a new runtime_profile knob,
add it both to an effective_* helper and to this function so
downstream consumers see consistent values regardless of which
surface they read from.
Sourcepub fn effective_skills_prompt_mode(
&self,
agent_alias: &str,
) -> SkillsPromptInjectionMode
pub fn effective_skills_prompt_mode( &self, agent_alias: &str, ) -> SkillsPromptInjectionMode
Resolve the effective skills prompt-injection mode for an agent: use an
explicit runtime-profile override when set, otherwise inherit the global
[skills] prompt_injection_mode value.
Keyed on the resolved runtime profile — the sanctioned surface for
per-agent runtime tunables — so agent-inline knobs stay inert.
Centralizing the fallback here keeps the system-prompt builder and the
read_skill tool-registration gate in lockstep on one effective mode,
so a compact prompt is never paired with a missing read_skill tool
(or a full prompt with a spurious one).
Sourcepub fn model_provider_for_agent(
&self,
agent_alias: &str,
) -> Option<&ModelProviderConfig>
pub fn model_provider_for_agent( &self, agent_alias: &str, ) -> Option<&ModelProviderConfig>
Resolve an agent’s model_provider reference ("<type>.<alias>") to
its concrete ModelProviderConfig entry. Returns None when the
agent doesn’t exist, the reference is unparseable, or the
<type>.<alias> pair doesn’t resolve in providers.models.
This is the lookup the orchestrator uses to build per-agent
model_provider runtime options via explicit <type>.<alias>
resolution — there is no concept of a “first” or “default”
provider. The matching split logic lives in
crates/zeroclaw-runtime/src/tools/delegate.rs::resolve_brain for
the delegation path; this helper exposes the same contract for the
channel-server startup path.
Sourcepub fn resolved_model_provider_for_agent(
&self,
agent_alias: &str,
) -> Option<(&'static str, &str, &ModelProviderConfig)>
pub fn resolved_model_provider_for_agent( &self, agent_alias: &str, ) -> Option<(&'static str, &str, &ModelProviderConfig)>
Resolve (provider_type, provider_alias, &ModelProviderConfig) for an
agent. Same lookup as model_provider_for_agent but also returns the
'static type key that downstream provider factories
(create_routed_model_provider_with_options, etc.) need. Returns
None when the agent has no model_provider set, when the reference
is unparseable, or when the resolved entry has been deleted from
providers.models.
Sourcepub fn agent_for_channel(&self, channel_alias: &str) -> Option<&str>
pub fn agent_for_channel(&self, channel_alias: &str) -> Option<&str>
Reverse-lookup the agent alias that owns a configured channel
(<type>.<alias>). Returns the first agent listing the channel in
its channels field. None when no agent owns the channel —
orphaned channels are a config error the orchestrator surfaces at
startup.
Sourcepub fn channel_workspace_dir(&self, channel_ref: &str) -> PathBuf
pub fn channel_workspace_dir(&self, channel_ref: &str) -> PathBuf
Workspace dir a channel’s inbound-media handler writes into. Resolves
the channel’s owning agent and returns <install>/agents/<alias>/workspace/;
falls back to data_dir for orphan channels (no owning agent enabled).
Sourcepub fn channels_by_alias(&self) -> Vec<ChannelAliasInfo>
pub fn channels_by_alias(&self) -> Vec<ChannelAliasInfo>
Schema-walk: every populated [channels.<type>.<alias>] block.
Type names come from the prop_fields() enumeration (kebab as the
macro emits them) so adding a new channel type via the macro
surfaces here without touching this code. Alias keys are HashMap
keys; not kebab-converted.
Sourcepub fn agent_for_cron_job(&self, cron_alias: &str) -> Option<&str>
pub fn agent_for_cron_job(&self, cron_alias: &str) -> Option<&str>
The single enabled agent that claims cron_alias through
[agents.<alias>].cron_jobs, or None when the claim is not unique.
This is the answer to “who owns this cron job” for ownership that lives
only in configuration: the scheduler’s execution fallback, declarative
sync, and upgrade ownership recovery all use it. A job row that already
carries a stored owner is resolved through that stored alias first (see
the runtime’s owner resolution), so this rule governs empty-alias rows
and not-yet-materialized declarative ids. agents is a hash map, so an
id claimed by two enabled agents would otherwise resolve to whichever
one iteration yields first, differing between processes; such a job is
refused rather than run under a coin-flip authority. See
Config::cron_job_claim for the reason a claim is not unique.
Sourcepub fn cron_job_claim(&self, cron_alias: &str) -> CronJobClaim<'_>
pub fn cron_job_claim(&self, cron_alias: &str) -> CronJobClaim<'_>
How [agents.<alias>].cron_jobs membership claims cron_alias.
Sourcepub fn agent_workspace_dir(&self, agent_alias: &str) -> PathBuf
pub fn agent_workspace_dir(&self, agent_alias: &str) -> PathBuf
Resolve the per-agent workspace directory for alias.
Returns the agent’s [agents.<alias>.workspace.path] override
when set (operator-explicit, e.g. for putting a workspace on a
different disk), otherwise derives
<install>/agents/<alias>/workspace/ from the install root
(the directory containing config.toml).
Per-agent workspaces live under
<install>/agents/<alias>/workspace/ and hold the agent’s
markdown memory (MEMORY.md), identity files (IDENTITY.md,
SOUL.md), and any other per-agent plaintext state. Shared
databases (SQLite memory, sessions, cost records) live under
config.data_dir instead and partition by agent at the row
level. Per-agent overrides via [agents.<alias>.workspace.path]
pin an arbitrary filesystem path (e.g. a different mount).
Sourcepub fn mcp_servers_for_agent(&self, agent_alias: &str) -> Vec<McpServerConfig>
pub fn mcp_servers_for_agent(&self, agent_alias: &str) -> Vec<McpServerConfig>
Effective MCP servers granted to an agent by its mcp_bundles.
Secure by default: omission is not a grant. An agent is reached via
resolved_agent_config; an unknown alias or one with no mcp_bundles
receives NO MCP servers. See Self::mcp_servers_for_bundles for how
a non-empty bundle list resolves to servers.
Sourcepub fn mcp_servers_for_bundles(
&self,
bundle_aliases: &[String],
) -> Vec<McpServerConfig>
pub fn mcp_servers_for_bundles( &self, bundle_aliases: &[String], ) -> Vec<McpServerConfig>
Resolve a set of [mcp_bundles.<alias>] references to the concrete
[mcp.servers] entries they grant.
Secure by default: omission is not a grant.
- An empty
bundle_aliasesgrants NO servers (Vec::new()). - The grant is the union of each referenced bundle’s
servers, in first-seen order with duplicates dropped. - Deny wins: a server name listed in ANY referenced bundle’s
excludeis removed from the grant, regardless of which bundle included it. - An unknown bundle alias grants nothing (it is skipped, not an error)
and a server name with no matching
[mcp.servers]entry grants nothing. Both fail closed: a misconfiguration narrows access, never widens it.
<install>/shared/ — directory shared across every agent on this
host. Holds skills, skill bundles, knowledge bundles, and any
other content not scoped to a single agent’s workspace. Distinct
from agent_workspace_dir(alias) (per-agent state) and
data_dir (databases + runtime state).
Sourcepub fn install_root_dir(&self) -> PathBuf
pub fn install_root_dir(&self) -> PathBuf
Install root: <install>/ derived from config_path’s parent. Used
to compute <install>/shared/, <install>/agents/, and the
skill-bundle directory defaults. Public so consumers (gateway, CLI,
SkillsService) share the same anchor.
Sourcepub fn agent(&self, agent_alias: &str) -> Option<&AliasedAgentConfig>
pub fn agent(&self, agent_alias: &str) -> Option<&AliasedAgentConfig>
Resolve an aliased-agent config by alias. None when the alias
isn’t configured; callers should treat this as a config error
rather than synthesizing a default.
Sourcepub fn resolved_runtime_agent_alias(&self) -> Option<&str>
pub fn resolved_runtime_agent_alias(&self) -> Option<&str>
Resolve the runtime-active agent alias the orchestrator binds
channels to. Mirrors the same selection logic as
start_channels() in zeroclaw-channels: prefer the migration-
synthesized "default" agent, otherwise fall back to the
lexicographically-smallest enabled alias. Returns None only
when no enabled agent is configured.
Used by per-agent infrastructure (TtsManager, TranscriptionManager)
to pick which agent’s tts_provider / transcription_provider
drives the manager’s resolved alias. Until the per-channel
dispatch refactor lands, the orchestrator runs in single-agent
mode, so all manager instances share the same resolved agent.
Sourcepub fn resolve_active_storage(&self) -> ActiveStorage<'_>
pub fn resolve_active_storage(&self) -> ActiveStorage<'_>
Resolve the active storage backend for the memory subsystem.
MemoryConfig.backend is a dotted reference (<backend>.<alias>) into
Config.storage.<backend>.<alias>. Bare backend names are interpreted
as <backend>.default for back-compat.
Returns ActiveStorage::None when no backend is configured, when the
backend is "none", or when the dotted alias does not resolve to a
configured entry.
Source§impl Config
impl Config
Sourcepub fn validate_auth(&self) -> Result<()>
pub fn validate_auth(&self) -> Result<()>
Validate the inbound-authentication sections ([oidc.<alias>],
[users], [permission_profiles]) on their own.
This is the ONE auth-specific validation boundary (RFC 7141). Full
Config::validate calls it, but so does authorization-policy
compilation: load_or_init deliberately tolerates a semantically
invalid config so an operator can boot to repair it, which means the
resolver cannot assume its input was validated. Running exactly these
checks again at compile/replace time guarantees that duplicate uids or
effective principal ids, invalid issuers, and dangling profile
references can never be installed as a serving policy — without making
auth activation contingent on every unrelated config field being valid.
Keys are sorted so the first error reported is deterministic.
Source§impl Config
impl Config
Sourcepub fn semantic_changed_paths(
previous: &Self,
candidate: &Self,
) -> Result<Vec<Vec<String>>>
pub fn semantic_changed_paths( previous: &Self, candidate: &Self, ) -> Result<Vec<Vec<String>>>
Compare unmasked semantic properties, independently of dirty-path bookkeeping. Serialized values are temporary; only opaque path components are returned. Serde-skipped loader diagnostics and process-local bookkeeping are excluded.
Sourcepub fn application_capability(&self, path: &[String]) -> ApplicationCapability
pub fn application_capability(&self, path: &[String]) -> ApplicationCapability
Resolve potential application from generated metadata, defaulting to reload.
Builds this snapshot’s property metadata on every call. To classify
several paths against one snapshot, build
Config::application_capabilities once and query it per path.
Sourcepub fn application_capabilities(&self) -> ApplicationCapabilities
pub fn application_capabilities(&self) -> ApplicationCapabilities
Snapshot this config’s per-property application metadata once, so
many paths can be classified without re-deriving prop_fields().
Sourcepub fn channel_external_peers(
&self,
channel_type: &str,
alias: &str,
) -> Vec<String>
pub fn channel_external_peers( &self, channel_type: &str, alias: &str, ) -> Vec<String>
The resolved peer policy for <channel_type>.<alias>: every granted
entry, plus every ignore entry as a PEER_DENY_PREFIX marker.
A [peer_groups.<name>] contributes when its channel field either
matches channel_type (type-wide group, applies to every alias of
that type) or matches the full dotted "<channel_type>.<alias>"
(instance-scoped group, applies to that one alias only).
This is an authorization input, not a list of addresses. Pass it to the
channel’s allowlist helpers, which apply denies before grants under that
channel’s identity rules. For a reachable account use
channel_addressable_peers.
Sourcepub fn channel_external_peers_for(
&self,
channel_types: &[&str],
alias: &str,
) -> Vec<String>
pub fn channel_external_peers_for( &self, channel_types: &[&str], alias: &str, ) -> Vec<String>
channel_external_peers for a channel written more than one way in
peer_groups (WeCom WebSocket is both wecom-ws and wecom_ws).
Resolving each spelling separately and concatenating the results loses
denies: an ignore under one spelling and a wildcard grant under the
other never meet. One pass over every matching group keeps the contract
whole.
Grants and denies are both returned as the operator wrote them, and
neither is applied here. Deciding a deny at this layer would need an
identity comparison, and only the channel knows what identity means:
Reddit reads u/alice and alice as one account, WhatsApp reads
+1555... and 1555... as one number, Nostr rewrites npub to hex.
Subtracting with a generic rule instead resolved the two sides under
different semantics, so an ignore the channel would have matched
disappeared before the channel ever saw it. The peer list now carries
the whole policy to the one place that can apply it consistently.
Sourcepub fn channel_addressable_peers(
&self,
channel_type: &str,
alias: &str,
) -> Vec<String>
pub fn channel_addressable_peers( &self, channel_type: &str, alias: &str, ) -> Vec<String>
Peers on <channel_type>.<alias> that name one reachable account.
channel_external_peers answers “who is authorized”, so it carries
wildcards and deny markers, neither of which is an address. Callers that
need somewhere to send a message want this instead.
Sourcepub fn channel_modality_peers(
&self,
channel_type: &str,
alias: &str,
modality: OutputModality,
) -> Vec<String>
pub fn channel_modality_peers( &self, channel_type: &str, alias: &str, modality: OutputModality, ) -> Vec<String>
Peer usernames for <channel_type>.<alias> from every
[peer_groups.<name>] whose channel matches (type-wide or dotted)
and whose output_modality is modality. Deduped, in group
iteration order.
This is the live-resolve counterpart of channel_external_peers,
filtered to one output modality. No cache — single source of truth
is self.peer_groups.
Sourcepub fn channel_voice_peers(
&self,
channel_type: &str,
alias: &str,
) -> Vec<String>
pub fn channel_voice_peers( &self, channel_type: &str, alias: &str, ) -> Vec<String>
Voice-peer usernames for <channel_type>.<alias> that should always
receive TTS voice replies: the channel_modality_peers of
output_modality = "voice".
Sourcepub fn channel_agent_scope_admins(
&self,
channel_type: &str,
alias: &str,
agent_alias: &str,
) -> Vec<String>
pub fn channel_agent_scope_admins( &self, channel_type: &str, alias: &str, agent_alias: &str, ) -> Vec<String>
Sender usernames authorized to issue /model --agent <model> on
<channel_type>.<alias> for agent agent_alias. A
[peer_groups.<name>] contributes when its channel matches
(type-wide or dotted), its admin_for_agent_scope = true, and its
agents list (if non-empty) contains agent_alias. Returns
deduped and sorted. Live-resolve against the Config this method
is called on — no internal cache. Edits to peer_groups take
effect at the next Config::channel_agent_scope_admins call; the
orchestrator gate reads through a snapshot of this Config, so
operator edits become visible after the runtime context is rebuilt
(daemon restart).
Sourcepub fn integration_descriptors(&self) -> Vec<IntegrationDescriptor>
pub fn integration_descriptors(&self) -> Vec<IntegrationDescriptor>
Collect the IntegrationDescriptor from every nested config that
declares one via #[integration(...)]. Adding a new toggleable
integration is one struct-level attribute on the new config + one
row in this method. The integrations registry consumes the result
without per-vendor branches.
Sourcepub fn unknown_keys(raw_toml: &str) -> Vec<String>
pub fn unknown_keys(raw_toml: &str) -> Vec<String>
Return top-level TOML keys in raw_toml that Config does not recognise.
Keys present in Config::default() serialization pass immediately.
Remaining keys are probed: the key is deserialized in isolation and
the result compared to the default — a changed output means serde
consumed it (covers Option<T> fields and #[serde(alias)] names).
V1 legacy keys (consumed by migration) are also accepted.
Sourcepub fn unknown_provider_families(raw_toml: &str) -> Vec<String>
pub fn unknown_provider_families(raw_toml: &str) -> Vec<String>
Return <kind>.<family> entries under [providers] in raw_toml
whose family is not a known typed slot (kinds: models, tts,
transcription). Serde silently drops these sections at deserialize
time, so a typo’d family ([providers.models.antropic.x]) or one
from a newer binary vanishes on reload: the alias “works” in the
session that created it, then disappears after restart.
Sourcepub fn prop_is_env_overridden(&self, path: &str) -> bool
pub fn prop_is_env_overridden(&self, path: &str) -> bool
Returns true if path was populated by a ZEROCLAW_* env-var
override at load time. O(1) HashSet lookup; safe to call per row in
list-rendering paths (config list, dashboard, quickstart).
pub async fn load_or_init() -> Result<Self>
Sourcepub async fn prepare_from_migrated_toml(
content: &str,
config_path: &Path,
data_dir: &Path,
) -> Result<Self>
pub async fn prepare_from_migrated_toml( content: &str, config_path: &Path, data_dir: &Path, ) -> Result<Self>
Hydrate one already-migrated config body exactly as a reload would, without replacing the config file.
This is the preparation step for config migration (see the
gateway’s migrate endpoint): the candidate must be fully hydrated
— strict parse into the current schema, computed paths attached,
secrets decrypted through the install’s store, env overrides
applied with their save-masking snapshots captured — and must pass
strict validation before the migrated file is allowed to replace
the live one. Any failure (parse, secret, unresolvable env path,
validation) refuses the migration with the original config file
untouched and nothing published. Migration acceptance is stricter
than resilient boot (Config::load_or_init warns and serves);
an operator-driven replacement may not install a config the
current schema rejects.
The caller supplies the canonical config_path and data_dir
(from the currently published config) so the prepared candidate is
exactly the config the next daemon generation would load from the
migrated file.
Sourcepub fn collect_warnings(&self) -> Vec<ValidationWarning>
pub fn collect_warnings(&self) -> Vec<ValidationWarning>
Collect non-fatal validation warnings — config that loads and
validates successfully (validate() returns Ok(())) but will fail
at runtime because of a logical inconsistency the schema cannot
enforce structurally.
Called by validate() (which emits each warning via tracing::warn!
for log visibility) and by the gateway HTTP API (which returns the
structured list in PropResponse / PatchResponse so dashboard
callers see the same signal the CLI sees on stderr).
Adding a new warning: append a check here, pick a stable code,
and document the code in validation_warnings.rs.
Sourcepub fn reply_pacing_entries(&self) -> Vec<(String, &dyn HasReplyPacing)>
pub fn reply_pacing_entries(&self) -> Vec<(String, &dyn HasReplyPacing)>
Walk every channel HashMap that carries reply pacing fields and yield
(dotted-path-prefix, &dyn HasReplyPacing) pairs. Used by validation
and by anywhere that wants a single source of truth for which channel
types participate in pacing.
Sourcepub fn validate(&self) -> Result<()>
pub fn validate(&self) -> Result<()>
Validate configuration values that would cause runtime failures.
Called after TOML deserialization and env-override application to catch obviously invalid values early instead of failing at arbitrary runtime points.
pub fn mark_dirty(&mut self, path: &str)
Sourcepub fn ensure_map_key_for_path(&mut self, path: &str) -> bool
pub fn ensure_map_key_for_path(&mut self, path: &str) -> bool
Auto-create the parent map key for a dotted set-prop path when it does
not yet exist, so a set_prop on a brand-new alias’s field materializes
the entry first.
Returns true iff it REFUSED to create the reserved default agent: a
set-prop surface should then surface a reserved-name error rather than the
generic “not configured” that the still-missing entry would otherwise
produce. Returns false in every other case (created, already existed, or
the path is not a map-keyed entry). The bool is advisory; statement-callers
that do not distinguish the reserved case may ignore it.
When it newly creates the alias, it also guarantees no phantom is left
behind: if path still doesn’t resolve afterward (e.g. an unknown tail
field), the just-created alias is rolled back before returning, so the
caller never observes a half-materialized entry from this probe alone.
Failures that happen after this returns (value coercion, a masked
secret, or a set_prop parse error) are the caller’s to contain. The
RPC config_set path does so by mutating a cloned Config and only
committing it on full success, so a discarded attempt drops the alias
with the clone — no tracked-tuple mirror of config transaction state is
exposed to the runtime.
#[resource_key] sections are excluded. Their keys are values drawn from
another domain (model id, voice, tool name) and may themselves contain
dots, so the first-dot split below would read
cost.rates.providers.models.openai.gpt-4.1.input_per_mtok as the bogus
alias gpt-4 plus a nonsense tail, and create_map_key skips
validate_alias_key for those sections so nothing else rejects it.
Rate rows are created explicitly through POST /api/config/map-key
instead.
Sourcepub fn ensure_map_or_list_key_for_path(&mut self, path: &str) -> bool
pub fn ensure_map_or_list_key_for_path(&mut self, path: &str) -> bool
Self::ensure_map_key_for_path, also creating a missing entry in a
keyed list section (plugins.entries, mcp.servers, model_routes,
embedding_routes), addressed by its natural key.
Only the local zeroclaw config patch command uses this. The operator
running it can already edit the config file directly, so creating a
row there adds no authority; a plugin with no config row otherwise has
no command that can create one, and plugin list needs a repair it can
print. The remote property-path APIs (the gateway’s HTTP set and
patch, the RPC set) keep Self::ensure_map_key_for_path, so this
change does not let them create a list row as a side effect of setting
a field. It is not a remote boundary for plugin grants: the explicit
map-key create (POST /api/config/map-key, RPC ConfigMapKeyCreate)
could already create a plugins.entries row, and property set can
already write egress_hosts on an existing row, both behind the
gateway’s authentication.
The same guarantees apply: an existing entry is left alone, and a new entry whose trailing field does not resolve is rolled back.
pub fn clear_dirty(&mut self)
pub fn set_prop_persistent(&mut self, name: &str, value_str: &str) -> Result<()>
pub fn set_secret_persistent(&mut self, name: &str, value: String) -> Result<()>
Sourcepub async fn save(&self) -> Result<()>
pub async fn save(&self) -> Result<()>
Full save. Refuses to overwrite an existing config file unless this
value was loaded from that exact file (loaded_from), so a default,
programmatically built, or repointed Config cannot replace an
operator’s config with a near-empty snapshot. Creating a
missing file (first run) always succeeds — a value that never read
a file gets exactly one create and must then reload or use
force_save(); force_save() is the explicit overwrite path.
Sourcepub async fn force_save(&self) -> Result<()>
pub async fn force_save(&self) -> Result<()>
Same as save(), but skips the loaded-provenance guard. Only for
callers that verifiably intend to replace an existing file with a
Config that never read it.
Destination-path checks still apply. To replace an existing file, set
config_path to the intended path with a nonempty parent directory.
A bare filename such as config.toml is refused if its runtime-resolved
destination already exists.
Sourcepub async fn save_dirty(&mut self) -> Result<()>
pub async fn save_dirty(&mut self) -> Result<()>
Incremental save: only the paths in self.dirty_paths are written
against the existing on-disk file. Non-dirty entries (including
secret ciphertext) are left untouched; dirty paths whose value
equals the schema default are removed from the doc instead of
written. Falls back to a full save() when the file doesn’t
exist yet. Clears the dirty set on success.
Trait Implementations§
Source§impl AsRef<Config> for LiveConfigReadGuard<'_>
impl AsRef<Config> for LiveConfigReadGuard<'_>
Source§impl<'de> Deserialize<'de> for Config
impl<'de> Deserialize<'de> for Config
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl JsonSchema for Config
impl JsonSchema for Config
Source§fn schema_id() -> Cow<'static, str>
fn schema_id() -> Cow<'static, str>
Source§fn json_schema(generator: &mut SchemaGenerator) -> Schema
fn json_schema(generator: &mut SchemaGenerator) -> Schema
Source§fn inline_schema() -> bool
fn inline_schema() -> bool
$ref keyword. Read moreSource§impl MaskSecrets for Config
impl MaskSecrets for Config
fn mask_secrets(&mut self)
fn restore_secrets_from(&mut self, current: &Self)
Auto Trait Implementations§
impl Freeze for Config
impl RefUnwindSafe for Config
impl Send for Config
impl Sync for Config
impl Unpin for Config
impl UnsafeUnpin for Config
impl UnwindSafe for Config
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> DeserializeOwned for Twhere
T: for<'de> Deserialize<'de>,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more