Recipe Drafter (describe a workflow, get a validated recipe)
The Recipe Drafter turns a natural-language description of an automation into a draft recipe, returned with its reasoning, warnings and any remaining validation errors. The draft is not saved to disk, so the caller decides whether to save it, edit it, or retry. It reads a bundled pattern library, validates the candidate, and can refine its own draft for up to three turns.
What it is
Audience: AI agents (with or without repo access) and Omniscio users curious how the "Create from description" flow works.
Where to find it
This is the drafter behind the "Create from description" recipe flow, and it has no screen of its own: a caller — an agent, a script, or the recipe-creation UI — sends a description and gets a draft recipe back, along with its reasoning, warnings and any remaining validation errors.
How it behaves
What it does
You give Omniscio a natural-language description of an automation — "every Monday morning, check three repos for failing CI and DM me a digest" or "audit each prompt in audit-reports/refactor-prompts/ with a 4-stage pipeline" — and Omniscio returns a draft RecipeConfig plus its reasoning, warnings, and any remaining validation errors. The draft is NOT saved to disk; the caller decides whether to save it (via RECIPE_SAVE_CONFIG), edit it, or retry.
When the drafter refuses
- Chitchat / non-recipe requests ("what's the weather?", "1+1?")
- Requests that need capabilities Omniscio doesn't have (live web scraping, arbitrary code execution)
The output is { recipe: null, source: "refused", reasoning: "..." } — caller surfaces the reasoning.
Cost & rate behavior
- Each turn is one Sonnet Messages API call. Typical one-shot ≈ $0.05–0.15. Refinement loop ≈ $0.20–0.50.
maxDrafterCostUsdhalts the loop when crossed.- The drafter does NOT cache; identical NL inputs produce a fresh call each time. (Caching is a future feature.)
- Auth: Messages API needs an API key. OAuth-only accounts get auto-fallback to the first API key account. No API key in the vault → handler returns an error envelope.
For agents
How it works
- Drafter reads the bundled pattern library (
audit-pipeline,fan-out-consolidate,red-team-gate,validate-then-act). - One Sonnet call. The system prompt has all four patterns inlined plus a brief recipe-schema cheat sheet.
- The model returns one JSON object on the last line of its response:
{ source, patternId?, parameters?, recipe?, reasoning }. - Omniscio takes the JSON:
source: "pattern"→ callinstantiatePattern(patternId, parameters)to materialize the recipe.source: "synthesized"→ use the inlinerecipedirectly.source: "refused"→ drafter declined (e.g. "what's the weather?"). Returnsrecipe: null.
- The validators (
runSemanticChecks+runWarningChecks) check the candidate. - If blocking errors AND remaining budget, the drafter sends a refinement message containing the previous draft + the errors and asks for a fix. Up to 3 refinement turns.
- Omniscio returns the latest draft + cost + token totals.
IPC surface
Channel: recipe:create-from-nl
// Input
{
"description": "audit each prompt in audit-reports/refactor-prompts/ with a 4-stage pipeline",
"existingDraft": null, // optional — pass a recipe to enter edit mode
"hints": { // all optional
"targetProjectId": "<uuid>",
"expectedStepCount": 5,
"preferredPatternId": "audit-pipeline",
"suggestedBudget": { "costUsd": 25, "minutes": 240 }
},
"maxDrafterCostUsd": 1.0 // optional — default $1.00
}
// Output (success envelope)
{
"recipe": { /* RecipeConfig | null */ },
"source": "pattern" | "synthesized" | "refused",
"patternId": "audit-pipeline",
"reasoning": "Matched audit-pipeline because the user described a 4-stage lane fan-out...",
"warnings": [], // ValidationError[] — non-blocking
"validationErrors": [], // ValidationError[] — blocking; if non-empty, recipe is best-effort
"drafterCostUsd": 0.08,
"drafterTokensUsed": 4200
}
Iteration mode
Pass the previous output's recipe as existingDraft and a change description:
{
"description": "change maxConcurrent to 3 and add a $20 cost cap",
"existingDraft": <previous recipe>
}
The drafter receives an edit-mode prompt: "Apply the user request to the existing draft. Keep unchanged fields intact."
Failure modes
DRAFTER_OUTPUT_PARSE_FAILED— model returned text without a recoverable JSON object on the final line.PATTERN_NOT_FOUND— model picked apatternIdthat doesn't exist. Usually a hallucination on small models.SYNTHESIZED_RECIPE_MISSING— model saidsource: "synthesized"but didn't include arecipefield.PATTERN_INSTANTIATION_FAILED— model passed bad parameters (wrong type, missing required, out-of-range).STEP_CAP_EXCEEDED/SUBRECIPE_NOT_FOUND/PROJECT_NOT_FOUND/ etc. — semantic validation errors. The drafter retries automatically; if the cap is hit before all errors clear, they surface invalidationErrors.
Prompts and tools
System prompts live in Main only and are NEVER returned over IPC. The reasoning field is the model's explanation, not the prompt.
Tools given to the model: NONE — v1 is a single-shot JSON-out call. Tool-use (Anthropic tool calls for list_patterns, validate_recipe, etc.) is a v2 consideration.
Related
- Pattern library: use-recipes.md, docs/developing/RECIPE_AUTHORING_GUIDE.md
- Roadmap: 2026-04-22-recipe-robustness-roadmap.md Phase 3 item #12
- Design doc: 2026-04-22-recipe-nl-create-ipc-design.md
Last verified 2026-09-26