You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Feature request — expose persisted memory to deterministic steps:/jobs: (and ideally a pre-agent job) so the "what work is there to do?" decision can be computed without an LLM turn.
Summary
Today all three memory stores — cache-memory, repo-memory, and comment-memory — are agent-facing tools: they're restored/downloaded into the agent job and consumed by the AI via the prompt. There is no supported way for deterministic code (a frontmatter steps: block, a custom jobs:, or an on.steps: pre-activation filter) to read the current memory state.
That's a real gap for any workflow where memory determines the work list. The natural design is: a cheap, deterministic step reads prior state ("what have I already processed?"), diffs it against reality, and produces the units of work — then the agent (or dispatched workers) execute. Because memory is agent-only, you're forced into one of two bad options:
Spend an LLM turn just to read memory and decide — nondeterministic, token cost, and slower, for what is pure set arithmetic.
Abandon the memory abstraction and hand-roll a parallel state store with cache: / actions/cache, duplicating the very thing cache-memory already provides (and losing its key scheme, branch-scoping, 7-day retention, comment round-trip, and the DIFC integrity model).
In practice option 2 is currently mandatory: even a frontmatter steps: block can't see cache-memory, because the cache-memory restore step is injected into the agent job after the user's steps: run — so a pre-agent steps: block reads empty state. I hit exactly this building an orchestrator/worker pair and had to add my own actions/cache beside the agent's memory.
Concrete scenario (OrchestratorOps + memory)
A scheduled orchestrator polls open PRs every 10 minutes and dispatches a worker per PR that is new or has new commits. The dedup key is "last-reviewed head SHA per PR" — ideal memory state. The ideal shape:
on:
schedule: [{ cron: "*/10 * * * *" }]tools:
cache-memory: # holds { "<pr>": "<last-reviewed-sha>" }key: code-review-statesafe-outputs:
dispatch-workflow:
workflows: [code-review-worker]steps:
# DeterministicOps: read memory, compute the dispatch list — NO agent needed
- run: | gh pr list --json number,headRefOid > prs.json jq ... (diff current SHAs against cache-memory state) > /tmp/gh-aw/agent/dispatch_list.json
Here the entire "decide what to dispatch" step is deterministic and cheap — if the step could read cache-memory. Today it can't, so the orchestrator must either burn an agent turn to read memory or keep a second cache.
Overlap with the documented patterns
This sits squarely in the seam between four existing patterns that almost compose but don't:
OrchestratorOps — "The orchestrator decides what to do and in what order." That decision is very often a function of memory (already-processed set, checkpoints). The pattern implicitly assumes the agent decides; there's no deterministic path from memory → dispatch list.
DispatchOps / dispatch-workflow — fan-out is already deterministic-friendly (a precomputed list of inputs), but the input to the fan-out (the work list) can't be derived from memory without the agent.
DeterministicOps — explicitly promotes "reliably collect and prepare data, then the AI agent reads the results," and even documents a Data Caching section and Deterministic Trigger Filtering (on.steps:). But its caching uses the separate low-level cache: frontmatter — not the memory abstraction. So the prep phase is blind to everything the workflow has stored in cache-memory/comment-memory.
MemoryOps — Pattern 1 (Exhaustive Processing) and Pattern 2 (State Persistence) keep todo/done/checkpoint state precisely so a run can "resume" and "mark each item done." Deciding which items remain from that state is textbook deterministic work — yet only the agent can read the state that drives it.
In short: DeterministicOps says "precompute deterministically, then let the agent reason," and MemoryOps says "persist state across runs," but you can't do both at once — precompute deterministically from persisted memory.
Proposed capability
Any one of these would close the gap (roughly increasing order of scope):
Restore memory before frontmatter steps:. Guarantee cache-memory/comment-memory/repo-memory are materialized at their documented paths (/tmp/gh-aw/cache-memory/, /tmp/gh-aw/comment-memory/, /tmp/gh-aw/repo-memory/) before the user's steps: run, so deterministic code in the agent job can read them. (Fixes the ordering; smallest change.)
Expose memory to on.steps: (pre-activation) so a deterministic filter can decide whether to run — and what to run — from memory.
A first-class "memory read" in a custom jobs: (e.g., a generated restore-memory job other jobs can needs:), so an orchestrator's compute-and-dispatch can be an ordinary deterministic job rather than an agent.
A read-only surface is enough for the work-planning use case; writes can remain agent/safe-output-mediated to preserve the integrity model.
Why it matters
Removes an unnecessary LLM turn (cost, latency, nondeterminism) from the most mechanical part of OrchestratorOps.
Stops pushing authors off the memory abstraction onto hand-rolled actions/cache, which fragments state and forfeits branch-scoping/retention/integrity guarantees.
Makes OrchestratorOps + MemoryOps + DeterministicOps genuinely composable — a cheap deterministic planner over durable memory, with the agent reserved for the actual reasoning/work.
Summary
Today all three memory stores —
cache-memory,repo-memory, andcomment-memory— are agent-facing tools: they're restored/downloaded into the agent job and consumed by the AI via the prompt. There is no supported way for deterministic code (a frontmattersteps:block, a customjobs:, or anon.steps:pre-activation filter) to read the current memory state.That's a real gap for any workflow where memory determines the work list. The natural design is: a cheap, deterministic step reads prior state ("what have I already processed?"), diffs it against reality, and produces the units of work — then the agent (or dispatched workers) execute. Because memory is agent-only, you're forced into one of two bad options:
cache:/actions/cache, duplicating the very thingcache-memoryalready provides (and losing its key scheme, branch-scoping, 7-day retention, comment round-trip, and the DIFC integrity model).In practice option 2 is currently mandatory: even a frontmatter
steps:block can't seecache-memory, because the cache-memory restore step is injected into the agent job after the user'ssteps:run — so a pre-agentsteps:block reads empty state. I hit exactly this building an orchestrator/worker pair and had to add my ownactions/cachebeside the agent's memory.Concrete scenario (OrchestratorOps + memory)
A scheduled orchestrator polls open PRs every 10 minutes and dispatches a worker per PR that is new or has new commits. The dedup key is "last-reviewed head SHA per PR" — ideal memory state. The ideal shape:
Here the entire "decide what to dispatch" step is deterministic and cheap — if the step could read
cache-memory. Today it can't, so the orchestrator must either burn an agent turn to read memory or keep a second cache.Overlap with the documented patterns
This sits squarely in the seam between four existing patterns that almost compose but don't:
dispatch-workflow— fan-out is already deterministic-friendly (a precomputed list of inputs), but the input to the fan-out (the work list) can't be derived from memory without the agent.on.steps:). But its caching uses the separate low-levelcache:frontmatter — not the memory abstraction. So the prep phase is blind to everything the workflow has stored incache-memory/comment-memory.todo/done/checkpoint state precisely so a run can "resume" and "mark each item done." Deciding which items remain from that state is textbook deterministic work — yet only the agent can read the state that drives it.In short: DeterministicOps says "precompute deterministically, then let the agent reason," and MemoryOps says "persist state across runs," but you can't do both at once — precompute deterministically from persisted memory.
Proposed capability
Any one of these would close the gap (roughly increasing order of scope):
steps:. Guaranteecache-memory/comment-memory/repo-memoryare materialized at their documented paths (/tmp/gh-aw/cache-memory/,/tmp/gh-aw/comment-memory/,/tmp/gh-aw/repo-memory/) before the user'ssteps:run, so deterministic code in the agent job can read them. (Fixes the ordering; smallest change.)on.steps:(pre-activation) so a deterministic filter can decide whether to run — and what to run — from memory.jobs:(e.g., a generatedrestore-memoryjob other jobs canneeds:), so an orchestrator's compute-and-dispatch can be an ordinary deterministic job rather than an agent.A read-only surface is enough for the work-planning use case; writes can remain agent/safe-output-mediated to preserve the integrity model.
Why it matters
actions/cache, which fragments state and forfeits branch-scoping/retention/integrity guarantees.Related
restore-memoryjob is introduced.Note
This issue was drafted with the help of GitHub Copilot.