Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jobs:
node-version: ${{ matrix.node }}
cache: npm
- run: npm ci
- name: Lint (biome)
run: npm run lint
- name: Typecheck
run: npm run typecheck
- name: Test (TestClock-deterministic)
Expand Down
33 changes: 32 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Agent workflows authored code-first with [`@nanobpm/workflow`](https://www.npmjs
| **Transport / client** | Effect surface over the C8 SDK ([S1 #437](https://github.com/camunda/orchestration-cluster-api-js/issues/437)) | [`src/effect/client.ts`](src/effect/client.ts) |
| **Agent runtime** | Effect job workers — `activate → handle → complete/fail` ([S2 #438](https://github.com/camunda/orchestration-cluster-api-js/issues/438)) | [`src/effect/worker.ts`](src/effect/worker.ts) |
| **Agents** | one `Effect` program per capability | [`src/agents/`](src/agents/) |
| **Human front-end** | an [`@nanobpm/urban`](https://www.npmjs.com/package/@nanobpm/urban) app reusing the built-in `taskInbox` surface to act on the `review` task | [`urban-app.ts`](urban-app.ts), [`nano.app.json`](nano.app.json) |

Effect is an **optional** layer at every SDK level — the demo opts in; it is never forced on the
Promise-based Camunda 8 SDK. It targets **Effect v4** (beta), pinned deliberately.
Expand Down Expand Up @@ -75,11 +76,12 @@ exact outcomes — no real waiting, no flakiness. See [`test/worker.test.ts`](te

## Run it

Prereqs: **Node ≥ 22.6** (uses `--experimental-strip-types` to run TypeScript directly).
Prereqs: **Node ≥ 22.6** (uses `--experimental-transform-types` to run TypeScript directly).

```sh
npm install
npm run typecheck # tsc --noEmit
npm run lint # biome check (lint + format); `npm run lint:fix` to apply
npm test # node --test, all deterministic (no engine, no network)
```

Expand All @@ -95,6 +97,35 @@ npm run deploy
`npm run deploy` deploys the model, leases the eight agent workers, starts one instance, and serves
until interrupted.

## The human front-end — acting on the `review` task

The `human(review)` step parks each instance on a user task until a reviewer approves the draft or
asks for a revision — nothing in `npm run deploy` completes it. Rather than build a bespoke reviewer
UI, the demo mounts [`@nanobpm/urban`](https://www.npmjs.com/package/@nanobpm/urban)'s
batteries-included **`taskInbox` surface** (ADR 0026): it lists the open `review` tasks, renders their
linked form, and completes them.

- [`nano.app.json`](nano.app.json) — the Urban app manifest: enables `surfaces.taskInbox` and declares
the form under `models.forms`.
- [`resources/forms/research-review.form`](resources/forms/research-review.form) — the form-js schema:
read-only `question` + drafted `finalAnswer`, a required `verdict` (approve / revise), and
conditional `revisionNotes`. Its field keys match the `review` task's I/O.
- [`urban-app.ts`](urban-app.ts) — a thin entrypoint: `runFromEnv` deploys the form and mounts the
surface against the **same** engine `npm run deploy` targets (no embedded engine, no duplicated
workers).

Run it alongside the deploy process:

```sh
npm run deploy # terminal 1 — deploys the flow, serves agents, starts an instance
npm run app # terminal 2 — deploys the form, serves the task inbox (default :8090/tasks)
```

Open [`http://localhost:8090/tasks`](http://localhost:8090/tasks), complete the `review` task, and the
loop converges: **approve** → `publish` → `archive`; **revise** → `record-revision` → re-`synthesize`
→ a fresh `review`. The app also embeds in the Nano console at `/console/app-view/research-agent/tasks`
(ADR 0057).

## License

Apache-2.0
29 changes: 29 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"$schema": "https://biomejs.dev/schemas/2.5.7/schema.json",
"vcs": { "enabled": true, "clientKind": "git", "useIgnoreFile": true },
"files": {
"includes": [
"src/**/*.ts",
"scripts/**/*.ts",
"test/**/*.ts",
"urban-app.ts",
"package.json",
"nano.app.json",
"biome.json",
"!bpmn",
"!resources",
"!node_modules"
]
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 120
},
"linter": {
"enabled": true,
"rules": { "preset": "recommended" }
},
"assist": { "enabled": true }
}
13 changes: 13 additions & 0 deletions nano.app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "https://nanobpm.io/spec-app/nano-app.schema.json",
"schemaVersion": 1,
"id": "research-agent",
"name": "Research Agent",
"codename": "Urban",
"surfaces": {
"taskInbox": { "enabled": true, "path": "/tasks" }
},
"models": {
"forms": ["resources/forms/*.form"]
}
}
Loading
Loading