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
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,27 @@ delivery is uncertain, so the transaction ends in `RECONCILIATION_REQUIRED` for
a person to settle. Longer walkthrough, including the `--guided` presentation
mode and the hand-driven stages: [docs/TUTORIAL.md](docs/TUTORIAL.md).

## Reference Execute server

You can host the public Execute HTTP contract on this machine, in one process.

```bash
pip install 'openadapt-flow[execute]'
openadapt-flow serve-execute --port 8787 --seed-mockmed
```

That command binds loopback, generates an Ed25519 key on first start, and
keeps it under `~/.openadapt/execute-ref/`. Health is `GET /health`. Submit
`openadapt.execute-request/v1` to `POST /v1/executions`, poll
`GET /v1/executions/{id}` until `terminal`, then read
`GET /v1/executions/{id}/receipt`. The same process also speaks MCP at
`POST /mcp`.

Receipts are self-signed with that local key. They aren't OpenAdapt
production Seals. `GET /seals/{id}` is the local verify page; it shows the
key fingerprint and a $0 meter. Counterparties that require an OpenAdapt Seal
still use Cloud.

## Record and rehearse your workflow

Install the extras for the surface that will record and replay the workflow:
Expand Down
80 changes: 80 additions & 0 deletions openadapt_flow/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@
command.
- ``console`` — serve the localhost-only operator console (a read-first web
UI over bundles / runs / skill libraries; requires the ``console`` extra).
- ``serve-execute`` — host the public Execute HTTP+MCP contract on this
machine (self-signed local receipts; not an OpenAdapt production Seal).
- ``emit-skill`` — emit an Agent Skills folder for a bundle.
- ``emit-mcp`` — emit a standalone MCP ``server.py`` for a bundle.
- ``connector`` — the BYOC (bring-your-own-cloud) outbound-pull daemon:
Expand Down Expand Up @@ -7616,6 +7618,42 @@ def _repair_store_flag(rp: argparse.ArgumentParser) -> None:
_add_deployment_flags(p)
p.set_defaults(func=_cmd_console)

p = sub.add_parser(
"serve-execute",
help=(
"Host the public Execute v1 HTTP+MCP contract locally. Receipts "
"are self-signed with a local key. They are not OpenAdapt "
"production Seals. Needs `pip install 'openadapt-flow[execute]'`"
),
)
p.add_argument(
"--port",
type=int,
default=8787,
help="Port (default: 8787)",
)
p.add_argument(
"--host",
default="127.0.0.1",
help="Bind address (default: 127.0.0.1)",
)
p.add_argument(
"--data-dir",
default=None,
help="Local data directory (default: ~/.openadapt/execute-ref)",
)
p.add_argument(
"--token",
default=None,
help="Bearer token (default: generated on first start in --data-dir)",
)
p.add_argument(
"--seed-mockmed",
action="store_true",
help="Write the synthetic MockMed ok and banner-lie admissions",
)
p.set_defaults(func=_cmd_serve_execute)

p = sub.add_parser(
"business-decisions",
help="Customer-runner typed-decision relay; it never resumes or acts.",
Expand Down Expand Up @@ -7873,6 +7911,48 @@ def _cmd_console(args: argparse.Namespace) -> int:
return 0


def _cmd_serve_execute(args: argparse.Namespace) -> int:
from importlib.util import find_spec

missing = [
name
for name in ("fastapi", "uvicorn", "openadapt_types")
if find_spec(name) is None
]
if missing:
raise SystemExit(
f"serve-execute needs {', '.join(missing)} — install the "
"execute extra: pip install 'openadapt-flow[execute]'"
)
from openadapt_flow.execute import SELF_SIGNED_NOTICE
from openadapt_flow.execute.app import serve
from openadapt_flow.execute.service import ExecuteService, default_data_dir

data_dir = Path(args.data_dir) if args.data_dir else default_data_dir()
store = ExecuteService(
data_dir,
token=args.token,
seed_mockmed=bool(args.seed_mockmed),
)
print("openadapt-flow reference Execute")
print(f" http://{args.host}:{args.port}")
print(f" data dir {data_dir}")
print(f" token {store.token}")
print(" issuer self_signed")
print(f" fingerprint {store.fingerprint}")
print(f" {SELF_SIGNED_NOTICE}")
if args.seed_mockmed:
print(" seeded MockMed admissions (ok + banner-lie)")
serve(
data_dir,
host=args.host,
port=args.port,
token=store.token,
service=store,
)
return 0


def _connector_flags(args: argparse.Namespace) -> dict[str, object]:
"""Collect the connector CLI flags into the settings-resolution dict."""
keys = (
Expand Down
24 changes: 24 additions & 0 deletions openadapt_flow/execute/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
"""MIT reference Execute server: one process, local self-signed receipts.

This is the engine-side host for the public Execute v1 request schema. It is
complete for one operator on one machine. It is not OpenAdapt Cloud: receipts
are self-signed with a local Ed25519 key, never an OpenAdapt production Seal.
"""

from __future__ import annotations

from typing import Literal

DEFAULT_HOST = "127.0.0.1"
DEFAULT_PORT = 8787
DEFAULT_DATA_DIRNAME = "execute-ref"
SELF_SIGNED_NOTICE: Literal[
"Self-signed. Counterparties that require an OpenAdapt Seal still use Cloud."
] = "Self-signed. Counterparties that require an OpenAdapt Seal still use Cloud."

__all__ = [
"DEFAULT_HOST",
"DEFAULT_PORT",
"DEFAULT_DATA_DIRNAME",
"SELF_SIGNED_NOTICE",
]
Loading