Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
49b60dd
Merge remote-tracking branch 'origin/main' into feat/narration-rules
abrichr Oct 18, 2026
8f90a16
feat(capture): scrub narration and store it as timed sentences
abrichr Oct 18, 2026
6da5aab
feat(flow): narration proposes branch guards; recordings or a person …
abrichr Oct 18, 2026
3824549
feat(flow): probe the narrated guard on a test copy; induce and narra…
abrichr Oct 18, 2026
f3e4a50
feat(flow): show narrated guards in visualize and repair show; narrat…
abrichr Oct 18, 2026
3d5f3d5
docs: narration in capture and flow, capability row in review
abrichr Oct 18, 2026
b6ec4e8
Merge remote-tracking branch 'origin/flow/probe-induction' into feat/…
abrichr Oct 18, 2026
9058afb
fix(flow): convert a capture without narration when its file is refused
abrichr Oct 18, 2026
1b15d54
fix(flow): review findings on narrated guards
abrichr Oct 18, 2026
e387c81
flow: keep the server's answer to a save, labelled same_screen
abrichr Oct 18, 2026
27e3569
Merge branch 'flow/desktop-readback' into flow/save-response-evidence
abrichr Oct 18, 2026
354cbc3
flow: server answer evidence review fixes
abrichr Oct 18, 2026
d5a2501
Merge branch 'flow/desktop-readback' into flow/save-response-evidence
abrichr Oct 18, 2026
21105d2
Merge flow/desktop-readback; regenerate claims report and artifact in…
abrichr Oct 18, 2026
ac1f101
Merge branch 'flow/desktop-readback' into flow/save-response-evidence
abrichr Oct 18, 2026
86e2e3c
Merge remote-tracking branch 'origin/main' into feat/narration-rules
abrichr Oct 19, 2026
c2a6f99
Merge branch 'flow/desktop-readback' into flow/save-response-evidence
abrichr Oct 19, 2026
2c99d59
Merge remote-tracking branch 'origin/main' into feat/narration-rules
abrichr Oct 19, 2026
534265b
fix(flow): lint and artifact inventory for narration
abrichr Oct 19, 2026
0533f97
Merge flow/desktop-readback; arm the server-answer log at the first save
abrichr Oct 19, 2026
665d8a8
Merge remote-tracking branch 'origin/main' into claude/mcp-teach-comp…
abrichr Oct 19, 2026
e8ec967
feat(agent): teach a workflow over MCP, then call it with no model calls
abrichr Oct 19, 2026
a8e1eb0
docs: link the teach-over-MCP PR in CAPABILITIES.md
abrichr Oct 19, 2026
568a111
Merge remote-tracking branch 'origin/claude/crystallize-from-prompt-8…
abrichr Oct 19, 2026
d9dbaee
Merge remote-tracking branch 'origin/main' into feat/narration-rules
abrichr Oct 19, 2026
328e4fb
fix(agent): bind each person's approval to one action; gate more off …
abrichr Oct 19, 2026
41dacc2
ci: pin two reviewed gitleaks false positives (key_dir in MCP teach t…
abrichr Oct 19, 2026
a3ad5e0
Merge remote-tracking branch 'origin/main' into flow/save-response-ev…
abrichr Oct 19, 2026
ca1020d
Merge origin/main into guard branch (brings in API steps #1269)
abrichr Oct 19, 2026
a94ffbe
WIP: seal every bundle and recording file under one index
abrichr Oct 19, 2026
1a73a54
Propose undo steps and verify them on a test copy
abrichr Oct 19, 2026
275c7f1
Merge remote-tracking branch 'origin/main' into flow/save-response-ev…
abrichr Oct 19, 2026
bf6c96f
undo propose: form-post and GraphQL reasons, offline rows, undo list …
abrichr Oct 19, 2026
835803f
Merge remote-tracking branch 'origin/main' into claude/gracious-chand…
abrichr Oct 19, 2026
1ceaf08
WIP: sealed runs, CLI guard, at-rest tests
abrichr Oct 19, 2026
b518949
undo propose: say what would close each step's gap; offline OpenEMR/o…
abrichr Oct 19, 2026
54d9962
feat(flow): guard an agent you already run (commit guard over CDP, ru…
abrichr Oct 19, 2026
bbc452f
WIP: keep compile, induce, qualify, admit, scaffold-verifier and undo…
abrichr Oct 19, 2026
9774017
test(flow): agent guard benchmark harness, e2e test, docs draft
abrichr Oct 19, 2026
59a45e6
WIP: sealed resume, attended state, nested undo runs
abrichr Oct 19, 2026
929f205
undo propose: fix test-copy snapshot identity; live MockLoan rows
abrichr Oct 19, 2026
7a9b20d
undo propose benchmark: Markdown table output
abrichr Oct 19, 2026
b7e1617
undo propose: results tables in docs, regenerate artifact inventory
abrichr Oct 19, 2026
43aa5ea
CAPABILITIES: link #1346
abrichr Oct 19, 2026
06c5af1
WIP: docs, measurements, record --no-encrypt
abrichr Oct 19, 2026
9cdba9a
Register the at-rest benchmark results in the public artifact inventory
abrichr Oct 19, 2026
6fe77bf
WIP: bind-record-checks keeps a sealed bundle sealed; approve on seal…
abrichr Oct 19, 2026
60eebbb
fix(flow): guard on its own connection, recorder on its own thread; r…
abrichr Oct 19, 2026
a9c4bd0
Merge remote-tracking branch 'origin/main' into claude/cool-tesla-63b116
abrichr Oct 19, 2026
7c04617
Seal look-up check proposals in encrypted recordings; refresh llms-full
abrichr Oct 19, 2026
6db638f
bench(flow): measure the agent guard on MockMed; docs and capability map
abrichr Oct 19, 2026
6c7f103
chore(flow): regenerate the public artifact inventory for the agent g…
abrichr Oct 19, 2026
f8a88ef
style: format the agent guard report
abrichr Oct 19, 2026
f045824
docs: link the agent guard PR in the capability map
abrichr Oct 19, 2026
42cec77
docs: state run 2's profile and the recorded reason no API step was p…
abrichr Oct 19, 2026
8339efd
flow: threat model and prompt-injection controls for teach and repair
abrichr Oct 19, 2026
1e8683f
docs: link #1359 in the capability map
abrichr Oct 19, 2026
2e2e176
undo propose: live MockMed row
abrichr Oct 19, 2026
bfa7d55
Regenerate public artifact inventory
abrichr Oct 19, 2026
67eafc2
Merge remote-tracking branch 'origin/main' into claude/gracious-chand…
abrichr Oct 19, 2026
48b0ad0
verify-run: a record outside the target that changed is collateral, n…
abrichr Oct 19, 2026
afdc517
Merge remote-tracking branch 'origin/main' into HEAD
abrichr Oct 19, 2026
9850b62
verify-run collateral change: compare values in canonical form (a bas…
abrichr Oct 19, 2026
26ef5db
Replayer undo hook: accept no effects (mypy)
abrichr Oct 19, 2026
fe5b410
Fix CI: mypy in sealed_set, test doubles without encryption hooks, Co…
abrichr Oct 19, 2026
4ba1401
Merge remote-tracking branch 'origin/main' into claude/cool-tesla-63b116
abrichr Oct 19, 2026
5796e05
Merge remote-tracking branch 'origin/main' into claude/gracious-chand…
abrichr Oct 19, 2026
34ceb6d
Merge remote-tracking branch 'origin/main' into flow/save-response-ev…
abrichr Oct 19, 2026
13e7a80
Merge origin/main into claude/mcp-teach-compile-a652e8
abrichr Oct 19, 2026
54924e6
Merge remote-tracking branch 'origin/claude/mcp-teach-compile-a652e8'…
abrichr Oct 19, 2026
1ae6440
undo_proposal: narrow selector value type (mypy)
abrichr Oct 19, 2026
5a67d8c
Merge remote-tracking branch 'origin/main' into claude/silly-mirzakha…
abrichr Oct 19, 2026
36a5fb7
Merge origin/main into the agent guard branch
abrichr Oct 19, 2026
3553c9b
test(flow): don't load mcp when collecting the MCP teach tests
abrichr Oct 19, 2026
2a302c6
verify-run collateral change: compare driver values with their stored…
abrichr Oct 19, 2026
1aac2b3
Merge remote-tracking branch 'origin/main' into claude/silly-mirzakha…
abrichr Oct 19, 2026
a0ee939
Merge remote-tracking branch 'origin/main' into claude/cool-tesla-63b116
abrichr Oct 19, 2026
6a0daa9
Merge remote-tracking branch 'origin/main' into flow/save-response-ev…
abrichr Oct 19, 2026
4999d26
Merge origin/main into claude/mcp-teach-compile-a652e8
abrichr Oct 19, 2026
9c67a6d
Merge origin/main into the agent guard branch (split files)
abrichr Oct 19, 2026
623b614
Merge #1335's updated branch into the agent guard branch
abrichr Oct 19, 2026
bf8e244
Merge remote-tracking branch 'origin/main' into HEAD
abrichr Oct 19, 2026
c3103a3
Merge remote-tracking branch 'origin/main' into HEAD
abrichr Oct 19, 2026
a1f06b1
bundle validation: omit forbid_collateral_change=False from sealed v2…
abrichr Oct 19, 2026
d20023e
Merge #1375 into batch safety
abrichr Oct 19, 2026
cc1b237
Merge #1354 into batch safety
abrichr Oct 19, 2026
e784cf8
Merge #1298 into batch safety
abrichr Oct 19, 2026
e968b2d
Merge #1291 into batch safety
abrichr Oct 19, 2026
b7a25ea
Merge #1346 into batch safety
abrichr Oct 19, 2026
a7cb4e5
batch safety: regenerate generated files
abrichr Oct 19, 2026
8db3caa
batch safety: regenerate inventory, verification report, command list…
abrichr Oct 19, 2026
89e4eb9
Merge #1359 into batch safety
abrichr Oct 19, 2026
ae0de30
Merge #1335 into batch safety
abrichr Oct 19, 2026
3cad704
Merge #1357 into batch safety
abrichr Oct 19, 2026
2757585
batch safety: regenerate generated files
abrichr Oct 19, 2026
97537a1
batch safety: public copy lists only shipped work
abrichr Oct 19, 2026
0ca42ac
Merge remote-tracking branch 'origin/main' into HEAD
abrichr Oct 20, 2026
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
5 changes: 4 additions & 1 deletion .github/workflows/packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ jobs:
python-version: "3.12"
cache: pip
- name: Install
run: pip install -e ../types -e '.[dev]'
run: pip install -e ../types -e '.[dev,agent]'
- name: Resolve Playwright version
id: pw
run: |
Expand Down Expand Up @@ -399,6 +399,9 @@ jobs:
tests/e2e/test_structural_action.py \
tests/e2e/test_compile_agent_e2e.py \
tests/e2e/test_code_action_e2e.py \
tests/e2e/test_mcp_teach_e2e.py \
tests/test_agent_guard.py \
tests/e2e/test_agent_guard_e2e.py \
--basetemp=runs/ci-critical --junitxml=runs/critical-junit.xml
- name: Fail if any critical test was skipped or none ran
run: |
Expand Down
8 changes: 8 additions & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ eb78575c688f06d7edc04afc69389aad10e1f5fa:packages/flow/tests/fixtures/terminal_v
# branch commit that added them. The lines carry gitleaks:allow from the next commit on.
3f0df2191a649540e79a621ac5406ebe2ff228e2:packages/flow/openadapt_flow/jit/authority.py:generic-api-key:101
3f0df2191a649540e79a621ac5406ebe2ff228e2:packages/flow/openadapt_flow/jit/authority.py:generic-api-key:390
# PR #1354: false positive on the code `Workflow.load(source_path, key=key,
# verify_integrity=True)` in bundle_sealing.py; no secret (the key comes from
# OPENADAPT_BUNDLE_KEY at run time).
a94ffbebccba96d9c2f9ca2016413f10c7526ff1:packages/flow/openadapt_flow/bundle_sealing.py:generic-api-key:282
# MCP teach (PR #1335): the generic-api-key rule matched the variable name `key_dir`
# in a principal_from_key(...) call in two tests. No credential.
e8ec96725c4451aa64cb97230c18d04b55d98503:packages/flow/tests/test_mcp_teach_surfaces.py:generic-api-key:147
e8ec96725c4451aa64cb97230c18d04b55d98503:packages/flow/tests/e2e/test_mcp_teach_e2e.py:generic-api-key:122
# PR #1367 (network capture redaction): the first commit's synthetic test values in
# test_network_capture_redact_json.py; the next commit builds them at run time.
52502adf407793c211fb3c0ac5aba37556206d8c:packages/flow/tests/test_network_capture_redact_json.py:generic-api-key:17
Expand Down
98 changes: 63 additions & 35 deletions CAPABILITIES.md

Large diffs are not rendered by default.

16 changes: 6 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,8 @@ jit.run(note="Recheck knee in ten days") # the program runs: 0 model calls, sav
```

[Compile a computer-use agent's run](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/JIT.md) has the full
example. This path runs web apps today. On Windows, RDP and Citrix, an agent can
already drive a recording through the MCP server's recording tools (on `main`,
not yet released), and the same compile path for those surfaces is being
built.
example. The same path compiles an agent's run in web apps and in Windows,
macOS, Linux, RDP and Citrix apps.

### Call programs from your agent

Expand Down Expand Up @@ -176,10 +174,9 @@ database read-back:

Both were equally correct here, and the agent matched or beat OpenAdapt in
three other tests. [Every result](https://openadapt.ai/compare/computer-use-agents)
is published. The program was only about a fifth faster because it still drives
every page, as the agent does; direct API steps compiled from the recording's
network traffic are in review
([#1269](https://github.com/OpenAdaptAI/OpenAdapt/pull/1269)). OpenAdapt isn't
is published. That program was only about a fifth faster because it drove every
page, as the agent does; the API step compiled from the recording's network
traffic removes the page steps for single-form saves. OpenAdapt isn't
affiliated with the OpenEMR project.

## Every backend
Expand Down Expand Up @@ -242,8 +239,7 @@ the right record is on screen, makes the entry, and reads the record back.
- **Works as a safety layer under any agent**: MCP tools, a guarded save, Agent Skills and a CLI.
- **Runs locally**: no model calls on healthy runs, patient data redacted, signed receipts.

[CAPABILITIES.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/CAPABILITIES.md) has the status, evidence and code for each,
including the few still being merged.
[CAPABILITIES.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/CAPABILITIES.md) has the evidence and code for each.

## What your agent gets back

Expand Down
188 changes: 140 additions & 48 deletions llms-full.txt

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@

> A person, or a computer-use agent once, shows a task in an application with no usable API. OpenAdapt compiles it into a program that makes the same entry every time with no model calls, confirms the right record before acting, reads the saved record back from the system of record, and stops instead of improvising or retrying.

This is the llms.txt for the OpenAdapt monorepo (github.com/OpenAdaptAI/OpenAdapt). Start with the capability map: https://github.com/OpenAdaptAI/OpenAdapt/blob/main/CAPABILITIES.md. It lists every capability with its status (released, in review, planned), its evidence (real app, synthetic, untested) and where it lives. Check it before concluding that OpenAdapt lacks something.
This is the llms.txt for the OpenAdapt monorepo (github.com/OpenAdaptAI/OpenAdapt). Start with the capability map: https://github.com/OpenAdaptAI/OpenAdapt/blob/main/CAPABILITIES.md. It lists every capability with its release (released, or on main for the next release), its evidence (real app, synthetic, untested) and where it lives. Check it before concluding that OpenAdapt lacks something.

## OpenAdapt in ten capabilities

Each capability is implemented in the
[OpenAdapt monorepo](https://github.com/OpenAdaptAI/OpenAdapt). "Released"
means it ships in the current PyPI packages; a pull request number means it is
being merged now.
means it ships in the current PyPI packages; "on main" means it ships in the
next release.

1. **Learns from any successful run, a person's or an agent's.** A person
records a task, or a computer-use agent does it once and OpenAdapt compiles
Expand Down Expand Up @@ -72,7 +72,7 @@ being merged now.
| Learns branching programs from several demonstrations, from repeated halts, and from many background runs. | `induce`, `teach-branch`, [SHADOW_MINING.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/capture/docs/SHADOW_MINING.md) |
| Chains programs across surfaces, and one program can switch surfaces, tabs and popups mid-run. | `compose`, `process`, [#1197](https://github.com/OpenAdaptAI/OpenAdapt/pull/1197) |
| Uses page structure first on web, Windows, macOS and Linux, with pixels as the fallback for remote desktops. Benchmarks labelled "vision-only" ran a deliberately pixel-only arm. | [RESOLUTION_LADDER.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/RESOLUTION_LADDER.md) |
| Runs steps as direct API calls; compiling them from captured network traffic is being merged. | `runtime/actuators/api.py`, [#1269](https://github.com/OpenAdaptAI/OpenAdapt/pull/1269) |
| Replaces a single HTML form submission with the request the app itself sends, compiled from the network traffic captured while recording, then reads the record back. | `api`, [API_TIER.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/API_TIER.md) |
| Repairs itself when the app changes: governed repair, agent-demonstrated fixes, fleet patches, and self-repair probed up to the save. | [REPAIR_LIFECYCLE.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/REPAIR_LIFECYCLE.md) |
| Compiles a computer-use agent's verified run, with no human demonstration needed. | [JIT.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/JIT.md) |
| Binds each approval to the exact screenshot and form state, and re-reads the form before saving. | [APPROVAL_MODES.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/APPROVAL_MODES.md) |
Expand Down
56 changes: 55 additions & 1 deletion packages/agent/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,8 @@ asyncio.run(main())

The SDK starts the server with only a few environment variables. To pass others, such as `OPENADAPT_BUNDLE_KEY`, add `env=` to `StdioServerParameters`.

To let your agent add workflows itself, see [Teach a new workflow from your agent](#teach-a-new-workflow-from-your-agent).

[scripts/smoke_client.py](scripts/smoke_client.py) is a fuller example that runs every sandbox case. From a clone of this repository, run `pip install -e .`, then:

```bash
Expand Down Expand Up @@ -284,7 +286,7 @@ Flow's [execution profiles](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/p
| `--timeout SECONDS` | How long one run may work (default 600). Time a person spends approving a save doesn't count. A run stopped at the limit is `not_sure_if_saved`. |
| `--approval-mode MODE` | Whether each save waits for approval. Without it, Flow decides, and a run stops before each save until it's approved (`each_item`). `not_gated` turns that off for every run this server starts; each result records it under `technical.approval_mode`. |
| `--delegate-approvals AGENT_ID` | Lets your agent answer a waiting save as `AGENT_ID` (an opaque id such as `agent:intake-bot`), with `list_approval_requests` and `answer_approval_request`. Flow accepts the answer only where the run's approver policy allows an agent for that step, and records the agent as the approver. By default only a person may answer. Needs openadapt-flow 2.2.0 or later. |
| `--admissions DIR` | Adds `prepare_admission`, `list_admissions` and `decide_admission`, the same steps as `openadapt-flow admit`, over recordings in `DIR/recordings` and shadow candidates in `DIR/shadow-candidates`. A person decides in your client's form. With `--delegate-approvals` and `--approver-grant`, your agent decides as that approver instead, under a grant a person signed that names it. It never decides an admission it prepared or one prepared on a server without `--delegate-approvals`, and never under the `regulated` policy pack. Accepting sets the workflow's runs to `problems_only`. The record names who decided, and for your agent the grant and who signed it. Not released yet. |
| `--admissions DIR` | Adds `prepare_admission`, `list_admissions` and `decide_admission`, the same steps as `openadapt-flow admit`, over recordings in `DIR/recordings` and shadow candidates in `DIR/shadow-candidates`. A person decides in your client's form. With `--delegate-approvals` and `--approver-grant`, your agent decides as that approver instead, under a grant a person signed that names it. It never decides an admission it prepared or one prepared on a server without `--delegate-approvals`, and never under the `regulated` policy pack. Accepting sets the workflow's runs to `problems_only`. The record names who decided, and for your agent the grant and who signed it. |
| `--approver-grant FILE` | With `--admissions` and `--delegate-approvals`: the approver grant a person signed (`openadapt-flow approver-grant sign`) that lets your agent decide admissions. Flow checks it on every decision. Without it only a person decides. |
| `--headed` | Shows the browser. A person needs it to continue or skip a stopped run in a web app. |
| `--extra-run-arg ARG`, `--flow-cli CMD` | Change how Flow is called. Either one can relax Flow's checks, for example `--extra-run-arg=--allow-unencrypted`. |
Expand Down Expand Up @@ -384,6 +386,58 @@ ChatGPT and Claude in a web browser can't start a server on your computer. To re

It claims the job, polls openadapt.ai over outgoing HTTPS, and asks you in the terminal before a chat account may drive it. Don't confuse it with the launcher's `openadapt connect`, which pairs a computer with OpenAdapt Cloud. [docs/MAILBOX_CLI.md](docs/MAILBOX_CLI.md) has the details.

### Guard an agent you already run

If your agent already drives a Chromium (a Playwright script, Playwright MCP, browser-use, or a computer-use agent with a browser), you don't have to move it onto these tools. Start its browser with a DevTools port, which is the one line you add, and run the guard next to it for each task:

```bash
openadapt-flow guard --cdp http://127.0.0.1:9222 --config guard.yaml --task task.json --out runs/task-0001
```

The guard holds every save the agent's tab sends until the record on the screen is the one `task.json` names. When it isn't, the save is blocked and the agent's page says why. A save that goes through is read back from the system of record (`VERIFIED`, `REFUTED` or `RECONCILIATION_REQUIRED`). `--observe-only` never blocks and shows what the guard would have done.

When a run reads back correctly, it becomes a draft in the teach dir that `guard.yaml` names, with a record check built from the app's own reads. A person confirms the check and admits the draft (`openadapt-flow compile-agent admit`); then `serve --teach verify.yaml --teach-dir <that dir>` serves it as a `taught_<name>` tool that makes no model calls. [GUARD_AN_AGENT.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/GUARD_AN_AGENT.md) has the files, what counts as a save, and the measurements.

### Teach a new workflow from your agent

`serve --teach` lets your agent add a workflow it doesn't have yet, without leaving the conversation. It does the task once through OpenAdapt; OpenAdapt checks the record it saved, compiles the run, and once the run is admitted your agent calls it as a tool. Every later call runs the compiled program with no model calls and reads the save back.

```bash
claude mcp add --scope user openadapt-teach -- uvx --python 3.12 --from 'openadapt-agent[tutorial]' openadapt-agent serve --teach verify.yaml --url https://emr-test.example.org --runs-dir ~/.openadapt/runs
```

`verify.yaml` needs only a `verifier:` section that reads the app's records (`rest`, `sql`, `fhir`, `graphql` or `file`), the same file `openadapt-flow record --verify` uses. The first run makes a real entry in the app, so point `--url` at a test copy with test records.

Your agent then:

1. Calls `teach_start` with the task (`{note}` for each input), this run's `inputs`, the `record_fields` the saved record must have (such as its patient id), and `on_screen`, the record's identity as the screen shows it (a name and an MRN).
2. Calls `teach_observe` and `teach_act` until the task is done. On the web, `teach_observe` lists the page as short lines with a ref for each control, and before every save OpenAdapt checks that the record's identity is shown next to the control. A save on the wrong record is refused and ends the run.
3. Calls `teach_finish`. OpenAdapt compiles the run and reads the app's records: exactly one record must have appeared, with every `record_fields` value and every input. The result is the draft: its steps, its inputs, the proposed record check, and what still needs a person.
4. Calls `teach_confirm_checks`. Your MCP client shows a person the proposed check, and only their answer there, with their name, confirms it. Your agent has no argument that confirms it.
5. Calls `teach_admit` with `canary_inputs`, the values each canary saves. A canary is a real save on the same record, so use values that are safe there.

`teach_admit` admits only under the rules in [JIT_ADMISSION.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/JIT_ADMISSION.md). The operator starts the server with `--teach-key agent.pem --teach-policy signed-policy.json`: the key of the agent registered with `openadapt-flow jit register --role agent`, and an admission policy a person signed with `openadapt-flow jit sign-policy`. The server records the run as that agent, so admitting it is self-admission, which the policy must allow (`allow_self_admission`). Without a key and a policy, `teach_admit` refuses and returns the command a person runs at a terminal instead:

```bash
openadapt-flow compile-agent admit <task dir> --admit-as "<your name>" --canary-param note="Canary test note"
```

Once the program is admitted, it is in `list_workflows` and `run_workflow` at once and has its own `taught_<name>` tool, and the server sends `notifications/tools/list_changed` to clients that support it. A server started later lists every program taught in its `--teach-dir`.

It works on a web app (`--url`) and on the app a deployment file's `backend:` section names (`--config deploy.yaml`): a native Windows, macOS or Linux window, or a local RDP or Citrix client window. Off the web, OpenAdapt can't read which record a form shows, so a person approves, in your client's form, every action that might save: any click except on a text field, a check box, a tab or a control that plainly navigates (Open, New, Cancel), any click at x,y, Enter, typing outside a text field, and shortcuts. Each answer covers that one action on the screen as it was; if anything changes first, the action isn't done. A client without forms can't save. RDP and Citrix have no control tree, and the Windows, macOS and Linux backends don't list controls yet, so off the web your agent needs `--teach-screens scrubbed` to see the screen, and clicks x,y pixels. Admission there fails closed for now: a pixel-only click carries no checked record identity, so the canary is refused and says why. Network RDP (`rdp_host`) is refused.

| Flag | What it does |
| --- | --- |
| `--teach VERIFY_YAML` | Adds `teach_start`, `teach_observe`, `teach_act`, `teach_finish`, `teach_abort`, `teach_status`, `teach_confirm_checks` and `teach_admit`, and turns on runs of taught workflows. |
| `--teach-dir DIR` | Where drafts and taught programs live (default `RUNS_DIR/teach`). |
| `--teach-key PEM`, `--teach-policy JSON` | The registered agent's encrypted key (passphrase in `OPENADAPT_JIT_KEY_PASSPHRASE`) and the signed admission policy. Only an agent key under a policy; an admitter key admits from CI with `openadapt-flow jit admit`. |
| `--key-dir DIR` | The JIT key directory (default `OPENADAPT_JIT_KEY_DIR` or `~/.openadapt/jit`). |
| `--teach-hold` | On the web, a person also approves every save in the first run. Without it, your agent names the identity the save gate checks (`on_screen`); a value every form shows proves nothing, and then only the record check after the run and the person confirming it catch a wrong record. |
| `--teach-screens scrubbed` | Adds `teach_screen`: the app's screen with identifiers scrubbed, and nothing shared if scrubbing fails. `unscrubbed` skips scrubbing. Off by default. |
| `--mode production --bundles DIR` | Serves your other workflows next to the taught ones. |

[COMPILE_AGENT.md](https://github.com/OpenAdaptAI/OpenAdapt/blob/main/packages/flow/docs/COMPILE_AGENT.md) describes the pipeline underneath: the harness, the record check, the canaries and the files it keeps.

## Track a long job

On long work, agents lose track of the rules they were given, miss information that arrives partway through, guess instead of asking, and skip checking their work ([OSWorld 2.0](https://arxiv.org/abs/2606.29537)). The task ledger keeps that state on the server, so your agent reads it instead of rebuilding it from its own history. It's on whenever runs or guarded saves are; `serve --no-ledger` turns it off.
Expand Down
Loading
Loading