Recipe Scratchpad

chevron-rightRelevant source fileshashtag

Purpose and Scope

The Recipe Scratchpad is an ephemeral, structured context-sharing system for multi-step recipe executions. It replaces verbose full-text output dumps between steps with auto-extracted key-value summaries, achieving 80-90% token savings while preserving essential context. The scratchpad is backed by Redis for performance and falls back to in-memory storage when Redis is unavailable.

This document covers the scratchpad's architecture, key layout, auto-extraction strategies, and integration with recipe execution. For information about recipe execution flow, see Recipe Execution. For details on S3 log storage, see Execution Configuration.

Sources: orchestrator/core/services/recipe_scratchpad.py:1-20


Problem Statement

Before the scratchpad system, recipe steps received context from previous steps as verbose text dumps—full agent responses, complete tool call results, and raw output strings. This approach had critical problems:

Problem
Impact
Example

Token Bloat

Steps 5+ consumed 10K+ tokens for context alone

5-step recipe: ~50K context tokens

LLM Confusion

Agents overwhelmed by irrelevant details

"Read all 47 PRs, then create 1 new PR" → agent reads PRs again

Cost Escalation

Linear token growth per step: O(n²)

10-step recipe: $2-5 in context tokens alone

Context Window Limits

Long recipes hit 128K limits

Execution failures at step 8-10

The scratchpad addresses these by extracting only the essential structured data from each step—URLs, key-value pairs, tool call summaries—and injecting it into subsequent steps as compact, queryable context.

Sources: orchestrator/core/services/recipe_scratchpad.py:1-16


Architecture Overview

spinner

The RecipeScratchpad class provides a key-value abstraction over Redis hashes, with automatic fallback to in-memory dictionaries. It's initialized once per recipe execution and accessed by all steps in sequence.

Sources: orchestrator/core/services/recipe_scratchpad.py:33-63, orchestrator/api/recipe_executor.py:632-636


Redis Key Layout

The scratchpad stores all execution context in a single Redis hash with structured field names:

spinner

Field Types

Field Pattern
Type
Purpose
Example Value

_input:{key}

String

Original trigger/input data

_input:issue_key"PILOT-123"

_meta:recipe_id

String

Recipe PK

"42"

_meta:total_steps

String

Step count

"5"

step_{N}:tool_results

JSON Array

Auto-extracted tool summaries

[{"action": "JIRA_GET_ISSUE", "key_data": {"issue_key": "PILOT-123"}}]

step_{N}:output_summary

String

First 500 chars of agent output

"Created PR #456 successfully..."

step_{N}:exports

JSON Object

Explicit agent-written data

{"pr_number": "456", "branch": "fix/pilot-123"}

Sources: orchestrator/core/services/recipe_scratchpad.py:8-16, orchestrator/core/services/recipe_scratchpad.py:99-143


Data Flow Through Recipe Execution

spinner

Key Integration Points

  1. Initialization (recipe_executor.py:632-636): Create scratchpad, write inputs and metadata

  2. Context Injection (recipe_executor.py:179-182): Format compact context before each step

  3. Auto-Extraction (recipe_executor.py:753-759): Extract and store results after each step

  4. S3 Upload (recipe_executor.py:466-509): Store full verbose logs separately

Sources: orchestrator/api/recipe_executor.py:559-777, orchestrator/core/services/recipe_scratchpad.py:174-252


Auto-Extraction Strategy

The scratchpad uses zero-LLM regex-based extraction to identify key data from tool calls and agent output. This ensures consistent, fast summarization without additional API costs.

Extraction Targets

spinner

Extraction Examples

Input
Extraction
Output Field

Tool result: {"data": {"html_url": "https://github.com/org/repo/pull/456"}}

urls: ["https://github.com/org/repo/pull/456"]

step_1:tool_results[{"action": "GITHUB_CREATE_PULL_REQUEST", "key_data": {"urls": [...]}}]

Tool result: "Branch: fix/PILOT-123\nPR: #456"

key_data: {Branch: "fix/PILOT-123", PR: "#456"}

step_1:tool_results[{"action": "...", "key_data": {...}}]

Agent output: 2000 chars

Truncate to 500 chars + "..."

step_1:output_summary"Created PR #456 successfully. The branch fix/PILOT-123 has been..."

Implementation

The extraction logic is in _extract_tool_summaries() and _extract_key_data():

Sources: orchestrator/core/services/recipe_scratchpad.py:254-362


Context Formatting

When a step requests context via format_context_for_step(N), the scratchpad builds a compact, structured summary of all prior steps:

spinner

Example Formatted Context

This formatted context replaces a 5000-token raw dump with ~500 tokens of essential information.

Sources: orchestrator/core/services/recipe_scratchpad.py:174-252


Storage Tiers

The recipe execution system uses a three-tier storage strategy to balance performance, cost, and queryability:

spinner

Tier Comparison

Tier
Storage
Retention
Size
Access Pattern
Use Case

Redis

RecipeScratchpad hash

Session lifetime

10-50 KB

Read/write during execution

Inter-step context passing

PostgreSQL

RecipeExecution.step_results JSONB

Permanent

200 KB

Read for UI rendering

Progress display, quick queries

S3

step_N.json files

Permanent

2-10 MB

Lazy-load on demand

Full debugging, audit trail

Compact Summary Format

The compact summary stored in PostgreSQL omits full output and tool results, replacing them with previews:

Sources: orchestrator/api/recipe_executor.py:466-553, orchestrator/core/services/recipe_scratchpad.py:1-16


Frontend Integration

The frontend displays recipe progress using compact summaries from PostgreSQL and lazy-loads full logs from S3 when users expand step details.

spinner

API Endpoint for Full Logs

The frontend lazy-loads full logs via:

This endpoint:

  1. Looks up the log_url from RecipeExecution.step_results[N]

  2. Downloads the S3 object (e.g. step_3.json)

  3. Returns the full log JSON to the frontend

Sources: frontend/components/workflows/recipe-step-progress.tsx:77-92, frontend/components/workflows/execution-kitchen.tsx:1-20


Fallback Behavior

The scratchpad gracefully degrades to in-memory storage when Redis is unavailable:

spinner

Fallback Guarantees

Operation
Redis Available
Redis Unavailable
Behavior Change

write_inputs()

HSET to Redis

Write to _fallback dict

None (transparent)

write_step_results()

HSET to Redis

Write to _fallback dict

None (transparent)

format_context_for_step()

HGETALL from Redis

Read from _fallback dict

None (transparent)

Persistence

Ephemeral (session)

Ephemeral (process)

⚠️ Lost if process crashes

Concurrency

Safe (Redis atomicity)

Not safe

⚠️ Single-process only

The fallback ensures recipe execution never fails due to Redis unavailability, but loses durability guarantees. In production, Redis should always be available.

Sources: orchestrator/core/services/recipe_scratchpad.py:40-94


Performance Impact

The scratchpad's token savings compound across recipe steps:

Token Savings Example (5-Step Recipe)

Approach
Step 1
Step 2
Step 3
Step 4
Step 5
Total

Verbose (old)

2K

5K (1×2K context)

10K (2×2K context)

17K (3×2K context)

26K (4×2K context)

60K tokens

Scratchpad (new)

2K

2.5K (500 context)

3K (1K context)

3.5K (1.5K context)

4K (2K context)

15K tokens

Savings

0%

50%

70%

79%

85%

75% total

Cost Impact

With GPT-4 Turbo pricing ($0.01/1K input tokens):

  • Old approach: 60K tokens × $0.01/1K = $0.60 per execution

  • New approach: 15K tokens × $0.01/1K = $0.15 per execution

  • Savings: $0.45 per execution (75% cost reduction)

For workspaces running 1000 recipes/month: $450/month savings.

Sources: orchestrator/core/services/recipe_scratchpad.py:1-20


Agent Export Tool

Agents can explicitly write key data to the scratchpad using the scratchpad_write tool, which is injected into every recipe step:

spinner

Tool Schema

This allows agents to bypass auto-extraction for critical data they know downstream steps need.

Sources: orchestrator/modules/tools/builtin/scratchpad_tool.py:1-60, orchestrator/api/recipe_executor.py:236-254


Code Integration Points

Initialization in Recipe Executor

orchestrator/api/recipe_executor.py:632-636

Context Injection Before Step Execution

orchestrator/api/recipe_executor.py:179-182

Auto-Extraction After Step Completion

orchestrator/api/recipe_executor.py:753-759

Manual Export During Execution

orchestrator/api/recipe_executor.py:236-254

Sources: orchestrator/api/recipe_executor.py:559-777, orchestrator/core/services/recipe_scratchpad.py:1-362


Last updated