{"record":{"id":"388e9e0124dfc6e6","repo":"tinyhumansai/openhuman","slug":"missing-system-prompt-custom-definitions-m","errorCode":null,"errorMessage":"{}: missing `system_prompt` — custom definitions must set an inline string or a file path","messagePattern":"(.+?): missing `system_prompt` — custom definitions must set an inline string or a file path","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/openhuman/agent/harness/definition_loader.rs","lineNumber":110,"sourceCode":"\n/// Load a single TOML file as an [`AgentDefinition`]. Stamps `source` to\n/// the absolute path.\n///\n/// Rejects definitions that omit (or leave blank) their `system_prompt`\n/// — built-in agents are loaded separately and have their prompts\n/// injected by [`crate::openhuman::agent::registry::agents::load_builtins`], so a\n/// file-loaded definition that arrives with the\n/// [`defaults::empty_inline_prompt`] placeholder is always a caller\n/// mistake. Custom definitions must set either\n/// `[system_prompt] inline = \"…\"` or `[system_prompt] file = \"…\"`.\npub fn load_file(path: &Path) -> Result<AgentDefinition> {\n    let content =\n        fs::read_to_string(path).with_context(|| format!(\"reading {}\", path.display()))?;\n    let mut def: AgentDefinition = toml::from_str(&content)\n        .with_context(|| format!(\"parsing {} as AgentDefinition TOML\", path.display()))?;\n    if let PromptSource::Inline(body) = &def.system_prompt {\n        if body.is_empty() {\n            bail!(\n                \"{}: missing `system_prompt` — custom definitions must set an inline string \\\n                 or a file path\",\n                path.display()\n            );\n        }\n    }\n    def.source = DefinitionSource::File(path.to_path_buf());\n    Ok(def)\n}\n\nfn user_home_agents_dir() -> Option<PathBuf> {\n    // Honour OPENHUMAN_HOME first if set; otherwise ~/.openhuman.\n    if let Ok(custom) = std::env::var(\"OPENHUMAN_HOME\") {\n        return Some(PathBuf::from(custom).join(\"agents\"));\n    }\n    match crate::openhuman::config::default_root_openhuman_dir() {\n        Ok(dir) => Some(dir.join(\"agents\")),\n        Err(error) => {","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/749120085864ce16e0f273c7b86fac7740b39c5b/src/openhuman/agent/harness/definition_loader.rs#L92-L128","documentation":"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 = \"...\".","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":"# before (~/.openhuman/agents/my-agent.toml)\nid = \"my-agent\"\nagent_tier = \"standard\"\n\n# after\nid = \"my-agent\"\nagent_tier = \"standard\"\n\n[system_prompt]\ninline = \"You are a focused assistant for ...\"","handlingStrategy":"validation","validationCode":"let def: AgentDefinition = toml::from_str(&content)?;\nif matches!(&def.system_prompt, PromptSource::Inline(body) if body.is_empty()) {\n    anyhow::bail!(\"{}: file definitions need [system_prompt] inline or file\", path.display());\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["agent","config","toml","validation","prompt"],"backgroundTag":"missing-config-field","analyzedSha":"749120085864ce16e0f273c7b86fac7740b39c5b","analyzedAt":"2026-08-17T21:21:45.363Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}