Skip to content

Composing Recipes

Recipes are composable units of behavior. Most users share and reuse full recipes. Packs exist for advanced authors who want to define new step-level logic.

The Mental Model

A Recipe is a container for steps (via packs). You compose recipes together.

ts
import { recipes } from "@geekist/llm-core/recipes";

const workflow = recipes
  .agent()
  .use(recipes.rag()) // Retrieval + synthesis
  .use(recipes.hitl()); // Pause for approval
js
import { recipes } from "@geekist/llm-core/recipes";

const workflow = recipes
  .agent()
  .use(recipes.rag()) // Retrieval + synthesis
  .use(recipes.hitl()); // Pause for approval

TIP

See the Packs & Recipes Reference for the full API on .step(), .priority(), and .override().

Tutorial: Swapping the Brain

Let's say you like the standard Agent Recipe, but you want to replace its "Planning" logic with your own version.

1. Import Recipes

You compose recipes via the unified handle.

ts
import { recipes } from "@geekist/llm-core/recipes";

const agent = recipes.agent();
type AgentRecipeConfig = Parameters<typeof agent.configure>[0];

2. Override the Planning Recipe

The standard agent uses a complex PlanningPack. Let's override it with a custom one.

ts
import { recipes } from "@geekist/llm-core/recipes";

const agent = recipes
  .agent()
  .use(recipes["agent.planning"]()) // overrides the default planning pack
  .build();

type Runtime = Parameters<typeof agent.run>[1];

Extending Behavior (Advanced)

Custom packs are an internal authoring primitive. Most users compose recipes and override existing packs via .use(...). If you need step-level authoring, treat it as an internal API and follow the packs reference.

Execution Order

Steps are executed based on a strict hierarchy:

  1. Dependencies: If B depends on A, A always runs first.
  2. Priority: Higher priority runs earlier (if dependencies allow).
  3. Alphabetical: If both above are equal, steps run alphabetically by name (deterministic).
ts
import { recipes } from "@geekist/llm-core/recipes";

type RecipePlan = {
  name: string;
  steps: Array<{ id: string; dependsOn: string[] }>;
};

const plan: RecipePlan = recipes.agent().plan();
console.log(plan.steps);

Next Steps

As you build more complex recipes with overrides and priority steps, you'll need to know what's happening under the hood.