Building with the API? Open the developer docs
Finmagine API & MCP — free tier to test • Pro/Max for full access • REST + MCP
Master agent-recipes.json through a complete learning overview and interactive flashcards
Every guide in this series so far has referenced agent-recipes.json in passing — the file behind the Agentic Workflow Explorer's 10 recipes, listed first alongside openapi.json in llms.txt. This guide goes inside the actual file — its real structure, the engineering discipline behind it, and a genuine drift bug its design was changed specifically to prevent.
Click any card to reveal the answer. Use the search box to find a specific topic.
openapi.json is mechanically generated from the actual handler code every time it runs — no human decides what goes in it beyond writing the handlers themselves. agent-recipes.json can't work that way, and its own generator script says exactly why in its header comment:
Knowing that screen_stocks and start_committee both exist as operations tells you nothing about whether chaining them together produces something useful — that judgment call has to come from a person who understands what the workflow is actually for. So every one of the 10 recipes was written by hand, then individually checked against the live openapi.json (tier, MCP tool name, response shape) before shipping — not assumed correct from memory of what was planned months earlier.
| Field | Type | What it's for |
|---|---|---|
id | string | Stable identifier, e.g. india_screen_to_committee |
title, description | string | Human-readable name and summary |
market | india | us | both | null | Which market this recipe targets |
required_tier | free | api_pro | api_max | Minimum tier needed — read directly from openapi.json's per-operation x-tier, not guessed |
async | boolean | Whether the recipe includes a start-then-poll step (Committee/Preset recipes) |
llm_required | boolean | Computed, not hand-typed — see the drift bug below |
status | complete | partial | prerequisite | complete = full working output; partial = a documented gap exists (see the recipe's own note); prerequisite = sets something up for other recipes rather than producing a research output itself |
quota | string or null | Free-text quota description, e.g. "5 committee runs / 24h" |
estimated_runtime | string or null | Free-text runtime estimate |
max_symbols | integer or null | Symbol cap where applicable |
output_contract | string | What the recipe's final output actually is |
failure_fallback, guardrail, note | string or null | Optional extra context, e.g. gap disclosure on status: partial recipes |
Every recipe's steps array is where the real chaining logic lives. Here's a genuine step from india_screen_to_committee:
| Field | What it's for |
|---|---|
id | Stable, recipe-local step identifier — referenced by other steps' depends_on/input_map. Unique within the recipe, not globally |
tool | Must match a real MCP tool name — verified against the live tool list before shipping |
input_from | Free-text chaining hint for human/agent readability — kept alongside the structured fields, not replaced by them |
depends_on | Step ids this step's request is built from. Empty array = no dependency. More than one entry = a genuine multi-parent DAG node — see the Agentic Workflow Explorer guide's honest-connector coverage |
input_map | Machine-readable chaining — see the dedicated section below |
transport | rest or mcp — kept explicit rather than assumed, since a future MCP-only tool shouldn't silently get treated as REST |
external_call | none | finmagine_free_tier | byo_key — see below |
max_items | Optional cap when a wildcard would otherwise map an unbounded array |
fixed_params | Constant values — see the dedicated section below |
| Value | Meaning |
|---|---|
none | Deterministic, no provider touched — e.g. screening, fast scan, risk audit |
finmagine_free_tier | Calls an LLM, but uses Finmagine's own key (e.g. the natural-language screener) — not the user's |
byo_key | Calls the user's own saved provider key and may consume real tokens/quota |
This is the concrete story behind why llm_required is computed rather than hand-typed. An earlier version of this file had a recipe-level llm_required boolean set directly by whoever wrote the recipe. The byo_key_setup recipe shipped with llm_required: false — even though one of its 3 steps, test_byo_key, makes a real, live call to an actual LLM provider to verify a saved key.
llm_required incorrectly on purpose; it was simply a second place the same fact had to be kept true, and it wasn't.
The fix: llm_required is no longer a field anyone sets directly. It's computed — true if any step's external_call is anything other than none:
input_map values follow one of two shapes, resolved by a small hand-rolled evaluator in developer/assets/explorer-core.js — deliberately not a full JSONPath library, since the actual need is narrow:
| Syntax | Meaning |
|---|---|
stepId.dot.path[*].field | Wildcard — maps every element of the array at that path |
stepId.dot.path[N].field | Index — picks a specific element by position |
URLSearchParams' own native array-to-string behavior in the execution engine, not by any manual joining logic in the recipe format. This distinction matters if you're writing your own executor: don't comma-join arrays yourself before building a POST body, or you'll send a string where the API expects a real array.
Some steps genuinely need a human or agent judgment call that can't be mechanically derived from a prior response — which preset id to launch, which provider to use, what secret to save. Those steps have a deliberately empty input_map: {}, and the schema explicitly documents this as expected, not an oversight: they need an interactive form in the Workflow Explorer UI, not silent auto-fill.
fixed_params maps a request param to a literal constant value, for params that must always be sent a fixed value rather than chained from a prior step's response — something input_map's dot-path syntax has no way to express, since it only resolves paths into previous step results, never arbitrary constants.
us_zero_cost_demo and us_trader_to_committee's fast_scan step describe "pass market:'us'" in prose (input_from), but before fixed_params existed, there was no mechanical field actually carrying that constant into the real request — the Workflow Explorer's first live execution of those recipes surfaced the gap directly, and fixed_params was added specifically to close it.
Because this file is hand-edited by a person, not machine-generated, it needed something machine-generated files don't: a schema to catch mistakes. agent-recipes.schema.json is a standard JSON Schema (draft 2020-12) added specifically to prevent field drift as recipes get edited over time — added per an external reviewer's suggestion.
It enforces the enums this guide has covered throughout — required_tier must be one of exactly 3 values, status one of exactly 3, external_call one of exactly 3, transport one of exactly 2 — plus structural requirements like every step needing a tool field and every recipe needing an output_contract.
The last 3 guides in this series cover specific named workflows built on everything covered so far:
See the API & Agent Integration hub for the full 12-guide roadmap.
Finmagine gives you 30+ computed financial ratios, sector benchmarks, FII/DII flows, the Finmagine Score, and AI-powered analysis — all in one place.