tinyhumansai/openhuman · error
{}: missing `system_prompt` — custom definitions must set an
Error message
{}: missing `system_prompt` — custom definitions must set an inline string or a file path What it means
Agent definitions loaded from disk must carry a real system prompt: if the TOML parses but system_prompt is the empty inline placeholder, load_file bails naming the file. Builtin definitions arrive with that placeholder so load_builtins can inject defaults later, which is why a file-loaded definition with an empty inline prompt is always an authoring mistake - file definitions must set [system_prompt] inline = "..." or [system_prompt] file = "...".
Source
Thrown at src/openhuman/agent/harness/definition_loader.rs:110
/// Load a single TOML file as an [`AgentDefinition`]. Stamps `source` to
/// the absolute path.
///
/// Rejects definitions that omit (or leave blank) their `system_prompt`
/// — built-in agents are loaded separately and have their prompts
/// injected by [`crate::openhuman::agent::registry::agents::load_builtins`], so a
/// file-loaded definition that arrives with the
/// [`defaults::empty_inline_prompt`] placeholder is always a caller
/// mistake. Custom definitions must set either
/// `[system_prompt] inline = "…"` or `[system_prompt] file = "…"`.
pub fn load_file(path: &Path) -> Result<AgentDefinition> {
let content =
fs::read_to_string(path).with_context(|| format!("reading {}", path.display()))?;
let mut def: AgentDefinition = toml::from_str(&content)
.with_context(|| format!("parsing {} as AgentDefinition TOML", path.display()))?;
if let PromptSource::Inline(body) = &def.system_prompt {
if body.is_empty() {
bail!(
"{}: missing `system_prompt` — custom definitions must set an inline string \
or a file path",
path.display()
);
}
}
def.source = DefinitionSource::File(path.to_path_buf());
Ok(def)
}
fn user_home_agents_dir() -> Option<PathBuf> {
// Honour OPENHUMAN_HOME first if set; otherwise ~/.openhuman.
if let Ok(custom) = std::env::var("OPENHUMAN_HOME") {
return Some(PathBuf::from(custom).join("agents"));
}
match crate::openhuman::config::default_root_openhuman_dir() {
Ok(dir) => Some(dir.join("agents")),
Err(error) => {View on GitHub (pinned to 7491200858)
Solutions
- Add a [system_prompt] section with either inline = "..." or file = "path/to/prompt.md".
- Reload definitions or restart so the registry picks up the fixed file.
- Lint agent TOMLs in CI or tooling to require a non-empty prompt for file-based definitions.
Example fix
# before (~/.openhuman/agents/my-agent.toml) id = "my-agent" agent_tier = "standard" # after id = "my-agent" agent_tier = "standard" [system_prompt] inline = "You are a focused assistant for ..."
Defensive patterns
Strategy: validation
Validate before calling
let def: AgentDefinition = toml::from_str(&content)?;
if matches!(&def.system_prompt, PromptSource::Inline(body) if body.is_empty()) {
anyhow::bail!("{}: file definitions need [system_prompt] inline or file", path.display());
} Prevention
- Lint every custom agent TOML for a non-empty system_prompt before shipping or reloading.
- Do not copy builtin templates that rely on defaults injection into file-based definitions.
- Prefer [system_prompt] file = "..." for long prompts so edits stay reviewable.
When it happens
Trigger: A custom agent TOML under ~/.openhuman/agents (or OPENHUMAN_HOME) omits the [system_prompt] table or sets inline to an empty string; a builtin-style template that relies on defaults injection was copied to a file without adding a prompt.
Common situations: Authoring a new file-based agent; trimming a template down and dropping the prompt block; assuming the registry will fill in a default prompt for file definitions (it will not).
Related errors
- agent `{parent}` is a `worker` tier and must not list `{chil
- Unsupported runtime kind: {other}
- Unsupported proxy service selector '{selector}'. Use tool `p
- Proxy is enabled but no proxy URL is configured. Set at leas
- proxy.scope='services' requires a non-empty proxy.services l
AI-assisted analysis of tinyhumansai/openhuman@7491200858 (2026-08-17).
Data as JSON: /api/errors/388e9e0124dfc6e6.
Report an issue: GitHub.