Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions docs/ADRs/0039-synchronous-workflow-call-event-dispatch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
title: "39. Synchronous workflow_call for event-driven agent dispatch"
status: Proposed
relates_to:
- agent-infrastructure
- operational-observability
topics:
- dispatch
- workflows
- observability
- workflow-call
---

# 39. Synchronous workflow_call for event-driven agent dispatch

Date: 2026-05-20

## Status

Proposed

## Context

The per-org event path still fans out from `dispatch.yml` to stage workflows
(`code.yml`, `review.yml`, …) via `gh workflow run` and `on: workflow_dispatch`
([ADR 0026](0026-stage-based-dispatch-for-agent-workflow-decoupling.md),
[ADR 0031](0031-reusable-workflows-for-action-installed-distribution.md)).
That hop is **asynchronous**: the dispatch job exits when GitHub accepts the
API call, not when the agent finishes. GitHub Actions does not link the
dispatched run to the caller in the UI — operators see unrelated top-level runs
in `.fullsend` with no parent workflow, which makes it hard to answer “is the
agent still running?” from a PR or issue and hard to debug failures.

Operational pain is documented across multiple issues:

- [#504](https://github.com/fullsend-ai/fullsend/issues/504) — enrolled-repo shim
can show green before review finishes or posts PR feedback.
- [#896](https://github.com/fullsend-ai/fullsend/issues/896) — agent runs lack
structured source/destination metadata; correlation requires log parsing.
- [#1048](https://github.com/fullsend-ai/fullsend/issues/1048) — `fullsend run`
and trigger resources are not linked; revives fragile `post-run-link` ideas.
- [#863](https://github.com/fullsend-ai/fullsend/issues/863) / [#529](https://github.com/fullsend-ai/fullsend/issues/529) —
`post-run-link` was dropped during `workflow_call` shim migration; run links
no longer posted on triggers.
- [#272](https://github.com/fullsend-ai/fullsend/issues/272) — no lifecycle
indicators (emoji reactions) on trigger comments/issues/PRs.
- [#957](https://github.com/fullsend-ai/fullsend/issues/957) / [#988](https://github.com/fullsend-ai/fullsend/issues/988) —
“working on this” comments without reliable failure follow-up when dispatch
and agent runs are decoupled.
- [#837](https://github.com/fullsend-ai/fullsend/issues/837) — failed review runs
should update PR status comments.
- [#763](https://github.com/fullsend-ai/fullsend/issues/763) — post-run feedback
should come from the agent App, not GitHub Actions bot identity.
- [#872](https://github.com/fullsend-ai/fullsend/issues/872) / [#934](https://github.com/fullsend-ai/fullsend/issues/934) —
silent failures when users cannot find the right `.fullsend` run.

Band-aids (extra comments, annotations, emoji, separate `post-run-link` jobs)
fight the async model. **Per-repo mode** already uses a synchronous
`workflow_call` chain (`reusable-dispatch.yml` → `reusable-{stage}.yml`;
[ADR 0033](0033-per-repo-installation-mode.md), PR #799). Per-org should
converge on the same property for the **event-driven** path.

Cross-repo shim → `.fullsend` is already `workflow_call` ([ADR 0029](0029-central-token-mint-secretless-fullsend.md),
[ADR 0034](0034-centralized-shim-routing-via-dispatch.md)). This ADR targets
only **in-config-repo** dispatch from `dispatch.yml` to agent stages.

Per-org installs are expected to add custom agent workflows in `.fullsend`.
The runtime `# fullsend-stage:` scanner ([ADR 0026](0026-stage-based-dispatch-for-agent-workflow-decoupling.md))
today wires those files without editing `dispatch.yml`; removing it requires
another discoverability path for org-specific agents.

## Options

### Option A: Keep `workflow_dispatch` + marker scan (status quo)

Preserves dynamic `# fullsend-stage:` discovery and nesting reset
([ADR 0031](0031-reusable-workflows-for-action-installed-distribution.md)).
Does not fix UI correlation or “dispatch succeeded ≠ agent done” ([#504](https://github.com/fullsend-ai/fullsend/issues/504)).

### Option B: `workflow_call` + compile-time dispatch sync (recommended)

Replace the scan/`gh workflow run` loop with conditional `workflow_call` jobs
in `dispatch.yml`. A scaffolded script (e.g. `scripts/sync-dispatch.sh`) scans
workflow files for `# fullsend-stage:` markers and regenerates a marked region
of `dispatch.yml` (one job per matched file; routing/mint stay hand-written).
Skills document running the script when stage workflows change; CI in `.fullsend`
runs the same logic in check-only mode and fails PRs when dispatch is out of
sync — stricter than the scanner, which silently skipped bad markers.

### Option C: Mitigations only (annotations, comments, reactions)

Implement [#896](https://github.com/fullsend-ai/fullsend/issues/896), [#1048](https://github.com/fullsend-ai/fullsend/issues/1048),
[#272](https://github.com/fullsend-ai/fullsend/issues/272) without changing dispatch
mechanism. Reduces pain but leaves orphan runs and early-success dispatch jobs.

## Decision

For **event-driven** agent dispatch (webhook → shim → routing → agent), eliminate
`workflow_dispatch` and `gh workflow run` between `dispatch.yml` and stage
execution. Use **Option B**: static `workflow_call` jobs aligned with
`reusable-dispatch.yml` ([ADR 0033](0033-per-repo-installation-mode.md)), with
`# fullsend-stage:` retained as metadata for a dispatch sync script, skills, and
CI check in each `.fullsend` repo (canonical script in the install scaffold,
same pattern as `reconcile-repos.sh`).

`workflow_dispatch` remains allowed for **non-event** entry points only (e.g.
`repo-maintenance.yml`, manual prioritize, admin/CLI triggers).

Prefer `dispatch.yml` → `reusable-*.yml@*` where possible to stay within four
`workflow_call` nesting levels. Dispatch sync tooling may ship after the
synchronous refactor; accepting this ADR does not block on it.

## Consequences

- PR/issue observers can use one Actions run to see agent completion without
hunting orphan `.fullsend` runs; mitigates [#504](https://github.com/fullsend-ai/fullsend/issues/504),
[#896](https://github.com/fullsend-ai/fullsend/issues/896), [#1048](https://github.com/fullsend-ai/fullsend/issues/1048),
and the silent-failure cluster ([#957](https://github.com/fullsend-ai/fullsend/issues/957),
[#988](https://github.com/fullsend-ai/fullsend/issues/988)); notification UX
may still need follow-up issues.
- **Supersedes mechanism** of [ADR 0026](0026-stage-based-dispatch-for-agent-workflow-decoupling.md)
Option C for the event path; centralized routing in `dispatch.yml`
([ADR 0034](0034-centralized-shim-routing-via-dispatch.md)) remains.
- Org custom agents stay addable via new workflow files plus marker + sync; until
tooling ships, `dispatch.yml` must be updated manually.
- Generated dispatch regions are not hand-edited; discoverability requires merge
via script or CI, unlike runtime scan on `main`.
- Per-org and per-repo dispatch shapes converge; enrolled-repo shims may need
`needs:` / concurrency review ([#504](https://github.com/fullsend-ai/fullsend/issues/504)).
Loading