Commit 90d8d23
feat: code-first agent orchestration in Effect (S3 demo) (#2)
* feat: code-first agent orchestration in Effect (S3 demo)
Author the research-agent orchestration code-first with @nanobpm/workflow
defineFlow (classify -> parallel retrieval -> convergence loop with human
review + non-interrupting SLA boundary -> publish/archive), within the
block-structured expressible subset, with LLM prompt-bound agent tasks.
Implement each agent as an idiomatic Effect program over an Effect job-worker
surface: typed error channel (transient vs permanent), Schedule exponential
backoff, Layer-injected Llm service, and Scope'd job leases. Add a thin Effect
client/worker surface over @nanobpm/workflow's Promise SDK as a stand-in for the
published @camunda8/orchestration-cluster-api/effect (#437/#438), swappable when
it ships.
Prove the orchestration's time-bounded behaviour deterministically with a
TestClock-based suite (retry backoff, per-call deadlines) plus model-derivation
assertions. Targets Effect v4 (beta), pinned.
Closes #1
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Josh Wulf <josh@magikcraft.io>
* fix: address Copilot review — error mapping, retry typing, revision feedback
- Llm.ts: map HTTP 429/5xx to TransientAgentError and other non-OK (4xx)
to PermanentAgentError; pass already-typed agent errors through the catch
instead of blanket-wrapping every failure as transient.
- worker.ts: loosen retrySchedule to Pick<AgentSpec, 'baseBackoff'|'maxRetries'>
and drop the now-unnecessary 'spec as AgentSpec<never>' cast in handleJob.
- errors.ts: correct the TransientAgentError doc — backoff exhaustion fails the
job with retries: 0 (raising an incident), not 'with retries left'.
- research-agent.ts: capture reviewer revisionNotes on the review task output and
feed it into the next synthesize round so revisions actually round-trip;
regenerated bpmn/research-agent.bpmn accordingly.
- worker.test.ts: drop no-op .then(async (r) => r).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Josh Wulf <josh@magikcraft.io>
* docs: adopt review decision C for reviewer-nudge SLA
Per PR #2 review (human decision C): keep the non-interrupting nudge
boundary and await an upstream @nanobpm/workflow fire-and-forget
(non-converging / end-event) boundary body rather than dropping the
nudge or moving a spurious token into the verdict gateway.
- research-agent.ts: document the boundary convergence limitation (the
nudge path merges into `review`, so a fired SLA can double-instantiate
it) and the intended fire-and-forget reviewer nudge on `review` timed
by `reviewNudgeSla`, tracked in #3.
- main.ts: explain `reviewNudgeSla` is reserved forward-looking config
for that future reviewer-nudge boundary, not dead config.
Tracking issue #3 files the upstream API feature request.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Josh Wulf <josh@magikcraft.io>
* fix: harden deterministic LLM, worker defects, and error detail
Address Copilot review (PR #2, round 4):
- Llm.ts: LlmDeterministic no longer echoes the prompt into its response.
The echoed head leaked prompt text into logs/variables and could inject
downstream parsing delimiters (classify splits on '|'), producing unstable
structured output. Now returns only the stable digest.
- Llm.ts: clip + normalize whitespace on non-OK LLM HTTP response bodies
before embedding them in the error reason (bounded, readable incidents).
- worker.ts: wrap the nano-sdk jobHandler in try/catch so an unexpected
runtime/layer defect fails the job deterministically (retries: 0) instead
of escaping as an unhandled rejection and risking silent redelivery.
- worker.test.ts: drop an unused recorder and its vacuous assertion.
Comment-only BPMN unchanged; typecheck clean; all 14 tests pass.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Josh Wulf <josh@magikcraft.io>
* fix: guard job-outcome observer so it can't fail the job
Wrap onOutcome in a swallowing notify() in both the success and defect
paths of the nano-sdk jobHandler: an observer throw (logging/metrics)
must not be mistaken for a worker defect (which would fail an
already-completed job) nor escape as an unhandled rejection.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Josh Wulf <josh@magikcraft.io>
* fix: unify worker-defect message and pin transient-retry assertions
Address Copilot suppressed advisories:
- worker.ts: emit the same `worker defect (...)` string as both the engine
incident errorMessage and the JobOutcome.reason so onOutcome logs/metrics
correlate with the engine's recorded message.
- test/worker.test.ts: the transient-retry test computed tries/result but never
asserted them; pin tries===3 and result._tag==="completed", and drop the
unused `actions` destructure.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Josh Wulf <josh@magikcraft.io>
* fix: make worker shutdown finalizers best-effort; drop unused recordedRound
Swallow rejections from ManagedRuntime.dispose() and worker stop/stopGracefully
in their scope finalizers so a shutdown-time failure surfaces as best-effort
cleanup instead of a scope-finalizer defect (graceful Ctrl-C / test teardown).
recordRevision no longer emits the unused recordedRound variable — the round
bump already lives in the model's io.output (=round + 1 -> round).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Josh Wulf <josh@magikcraft.io>
* fix: map search sourceCount into process variables
Honor the Findings envelope contract: search-web/search-kb declare and
return sourceCount, but the model's io.output only mapped =findings, so
Zeebe ioMapping dropped sourceCount. Map =sourceCount into webSourceCount
/kbSourceCount and regenerate bpmn/research-agent.bpmn.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Josh Wulf <josh@magikcraft.io>
---------
Signed-off-by: Josh Wulf <josh@magikcraft.io>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent 680ac56 commit 90d8d23
28 files changed
Lines changed: 2109 additions & 13 deletions
File tree
- .github/workflows
- bpmn
- prompts
- scripts
- src
- agents
- effect
- model
- test
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
9 | 9 | | |
10 | 10 | | |
11 | 11 | | |
12 | | - | |
13 | | - | |
14 | | - | |
15 | | - | |
16 | | - | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
17 | 18 | | |
18 | | - | |
19 | | - | |
| 19 | + | |
| 20 | + | |
20 | 21 | | |
21 | | - | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
22 | 27 | | |
23 | | - | |
24 | | - | |
25 | | - | |
| 28 | + | |
26 | 29 | | |
27 | | - | |
| 30 | + | |
| 31 | + | |
28 | 32 | | |
29 | | - | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
30 | 97 | | |
31 | 98 | | |
32 | 99 | | |
| |||
0 commit comments