{"record":{"id":"635881b1e9fc806e","repo":"tinyhumansai/openhuman","slug":"missing-agent-parameter","errorCode":null,"errorMessage":"Missing 'agent' parameter","messagePattern":"Missing 'agent' parameter","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/openhuman/agent/tools/delegate.rs","lineNumber":126,"sourceCode":"                    \"type\": \"string\",\n                    \"minLength\": 1,\n                    \"description\": \"The task/prompt to send to the sub-agent\"\n                },\n                \"context\": {\n                    \"type\": \"string\",\n                    \"description\": \"Optional context to prepend (e.g. relevant code, prior findings)\"\n                }\n            },\n            \"required\": [\"agent\", \"prompt\"]\n        })\n    }\n\n    async fn execute(&self, args: serde_json::Value) -> anyhow::Result<ToolResult> {\n        let agent_name = args\n            .get(\"agent\")\n            .and_then(|v| v.as_str())\n            .map(str::trim)\n            .ok_or_else(|| anyhow::anyhow!(\"Missing 'agent' parameter\"))?;\n\n        if agent_name.is_empty() {\n            return Ok(ToolResult::error(\"'agent' parameter must not be empty\"));\n        }\n\n        let prompt = args\n            .get(\"prompt\")\n            .and_then(|v| v.as_str())\n            .map(str::trim)\n            .ok_or_else(|| anyhow::anyhow!(\"Missing 'prompt' parameter\"))?;\n\n        if prompt.is_empty() {\n            return Ok(ToolResult::error(\"'prompt' parameter must not be empty\"));\n        }\n\n        let context = args\n            .get(\"context\")\n            .and_then(|v| v.as_str())","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/src/openhuman/agent/tools/delegate.rs#L108-L144","documentation":"The `delegate` agent tool was invoked without a usable `agent` argument: args[\"agent\"] is absent or not a JSON string (delegate.rs:126). The tool's JSON schema marks agent and prompt required, and the available agent ids are enumerated in the parameter description, so this is a malformed tool call. The empty-after-trim case is handled separately as a soft ToolResult::error, not this anyhow error.","triggerScenarios":"LLM omits the agent field or passes null/number/object; a hand-rolled caller serializing args with a wrong key (agent_name instead of agent); schema drift between the advertised tool schema and the caller.","commonSituations":"Smaller models ignoring the required list; renamed parameters after tool-description edits; client code building args from unvalidated input.","solutions":["Pass \"agent\" as a non-empty string, one of the ids listed in the tool's parameter description","Align the caller's arg keys with the schema (agent, prompt, optional context)","Validate args against the tool's JSON schema before invoking if you wrap the tool","Feed the error back to the model — it is self-correctable on retry"],"exampleFix":"// before\n{ \"prompt\": \"index the repo\", \"agent_name\": \"indexer\" }\n\n// after\n{ \"agent\": \"indexer\", \"prompt\": \"index the repo\" }","handlingStrategy":"type-guard","validationCode":"// Validate before invoking the delegate tool\nfunction canCallDelegate(args: unknown): boolean {\n  const a = args as Record<string, unknown>;\n  return typeof a?.agent === \"string\" && (a.agent as string).trim() !== \"\"\n      && typeof a?.prompt === \"string\" && (a.prompt as string).trim() !== \"\";\n}","typeGuard":"function isDelegateArgs(a: unknown): a is { agent: string; prompt: string; context?: string } {\n  if (typeof a !== \"object\" || a === null) return false;\n  const v = a as Record<string, unknown>;\n  return typeof v.agent === \"string\" && v.agent.trim() !== \"\"\n      && typeof v.prompt === \"string\" && v.prompt.trim() !== \"\"\n      && (v.context === undefined || typeof v.context === \"string\");\n}","tryCatchPattern":"// In Rust wrappers: convert the anyhow error into model-visible tool feedback\nif let Err(e) = tool.execute(args).await {\n    if e.to_string().contains(\"Missing 'agent'\") {\n        return Ok(ToolResult::error(\"delegate requires 'agent' (see listed ids) and 'prompt'\"));\n    }\n    return Err(e);\n}","preventionTips":["Keep the required list ([\"agent\",\"prompt\"]) in sync with execute()'s reads","Enumerate valid agent ids in the parameter description so the model can comply","Validate tool-call args against the advertised JSON schema before dispatch"],"tags":["rust","tool","arguments","llm","delegation"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}