Skip to content
Loops
AGH RuntimeLoops

Extending Loops

How extensions add Loop definitions, actions, gate checks, and watch sources — reusing AGH's existing surfaces, with one new bridge capability.

Audience
Operators running durable agent work
Focus
Loops guidance shaped for scanability, day-two clarity, and operator context.

Loops extend through AGH's existing extension surfaces. Almost everything is wiring you already have — the tool registry, the resource projection, the hook catalog — and the only new protocol surface is a single bridge capability for watch sources.

Ship definitions as resources.loops

An extension publishes Loop definitions the same way it publishes agents or skills: a directory list under resources.loops in its manifest.

{
  "resources": {
    "loops": ["loops"]
  }
}

The daemon projects each definition as a loop resource carrying matchable metadata only — name, scope, catalog, and start bindings — while the full agh.loop/v1 YAML stays on the filesystem. Loop definitions resolve through marketplace, user, additional, and workspace layers (workspace wins). A shipped Loop appears in the catalog next to the default dev-cycle Loops.

Actions are tools

A Loop action kind is a tool ID. The action registry is a thin adapter over the runtime tool registry — there is no second registry and no second orchestrator — so every native, extension, and MCP tool is already a Loop action.

To add a Loop action, publish a tool with the tool.provider capability. Tag it loop.action or loop.gate in a toolset if you want it grouped for authors. Because actions run through the one RuntimeRegistry.Call path, they inherit policy, approval, redaction, and observability for free.

Gate extension checks

A gate criterion of type: extension calls an extension tool and interprets its structured output (or exit code) as a verdict. It rides the same tools/call path as any other tool — no new bridge method.

- id: policy_check
  type: extension
  tool: ext__acme_policy_scan
  inputs: { target: "{{ .inputs.slug }}" }

The other three check kinds — command, agent-judge, human — are native.

Watch sources

A watch-source node waits for an external signal and ticks the Loop when the signal is ready. It is the one place Loops needed a new bridge surface: the capability loop.watch_source plus the daemon→extension service method watch/poll.

An extension declares a watch source with the SDK:

extension.watchSource("acme.pull_request", {/* options */}, async (spec, expectedStateDigest) => {
  // return { ready, state_digest, payload, settled_at }
});

extension.watchSource() auto-declares the loop.watch_source capability and registers the watch/poll handler. The daemon calls it synchronously — { spec, expected_state_digest } in, { ready, state_digest, payload, settled_at } out — driven by the coordinator's own task run (claim → poll → yield → re-claim), never a parked goroutine. There is no push path in this version; the coordinator polls.

Watch runtime behavior

Once a watch Loop starts, its lifecycle differs from a delivery Loop:

  • watching — between ticks the run is dormant in the watching state, re-woken by the next poll. It is not consuming a generation while it waits.
  • Unbounded cap — watch Loops default iteration_cap: 0, rendered . A 0 cap never produces exhausted, because there is no fixed count of "done."
  • no-op on clean ticks — a tick that finds nothing to do ends the generation no-op, never a fake done. A clean watch tick is honest idleness.
  • Stall on silence — if a watched source goes silent past its window, the run ends stalled (reason watch_source_silence), not done. Silence is measured against last_progress_at plus the source's window.

The default dev-cycle reviews-watch Loop is a watch Loop: it holds watching, fetches and remediates each new batch of CodeRabbit review comments as a generation, and reports no-op when a tick finds nothing unresolved. It requires gh to be installed and authenticated.

What stays put

  • Hooks — extensions observe or gate Loops through the existing loop.* hook family; no new hook wiring.
  • Agent tools — the agh__loop_* toolset is native and standard; extensions do not add loop management tools.
  • The network wire — Loops are a runtime feature. Extensions do not carry Loop execution over AGH Network.

On this page