Skip to content

Native cache step type + step template/macro system for reusable patterns #55

Description

@ameet

Problem

Multi-step patterns that repeat across many flows have no abstraction mechanism. Two specific cases:

1. Caching (6-step boilerplate per flow)

The recommended caching pattern requires 6 steps every time:

  1. buildCacheKey — deterministic key from inputs
  2. readCacheFile — file-read with onError: continue
  3. checkCache — evaluate hit/miss/expired
  4. buildResult — actual computation
  5. buildCacheEntry — quality gate + serialize
  6. writeCacheFile — persist to disk with null guard

In a 90+ flow codebase, ~20 flows implement this. That's ~120 steps of identical boilerplate, each with the same bug surface: step ordering (buildResult must precede buildCacheEntry), null guards on writeCacheFile, TTL math, and quality gates. We maintain a regression test specifically to catch cache ordering bugs.

Proposed solution — native cache step:

{
  "id": "cachedResearch",
  "type": "cache",
  "cache": {
    "namespace": "research",
    "key": "{{$.input.domain}}-{{$.input.depth}}",
    "ttlDays": 30,
    "qualityCheck": "output && output.length > 100",
    "compute": [
      { "id": "doWork", "type": "bash", "bash": { "command": "..." } }
    ]
  }
}

The CLI handles: file I/O, TTL evaluation, null guarding, and only runs the compute steps on cache miss. One step replaces six.

2. Repeated multi-step patterns (3-step boilerplate per invocation)

Beyond caching, several 3-step patterns repeat across 30+ flows:

  • LLM call pattern: file-write prompt → bash claude --print → code parse envelope/fences
  • HTTP POST + persist: code build payload → bash POST to server → bash upload result
  • API lookup: code build params → bash curl → code parse response

We extracted shared utility flows for these, but sub-flow output wrapping (#21, #47) makes them fragile. A template/macro system would let you define reusable step groups that expand inline (no sub-flow overhead):

{
  "id": "analyzeCompany",
  "type": "template",
  "template": "llm-call",
  "params": {
    "prompt": "{{$.steps.buildPrompt.output}}",
    "model": "haiku",
    "outputFormat": "json"
  }
}

Templates would be defined once (e.g., in a .one/templates/ directory) and expanded at flow load time — avoiding the sub-flow output path issues entirely.

Impact

Alternatives considered

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions