amduat-api/docs/v2-app-developer-guide.md
2026-02-07 20:27:12 +01:00

241 lines
7 KiB
Markdown

# Amduat v2 App Developer Guide
This is the compact handoff guide for building an application against `amduatd` v2.
For machine-readable contracts, see `registry/amduatd-api-contract.v2.json`.
## 1) Runtime Model
- One daemon instance serves one ASL store root.
- Transport is local Unix socket HTTP.
- Auth is currently filesystem/socket permission based.
- All graph APIs are under `/v2/graph/*`.
Minimal local run:
```sh
./vendor/amduat/build/amduat-asl index init --root .amduat-asl
./build/amduatd --root .amduat-asl --sock amduatd.sock --store-backend index
```
If you run with `--store-backend index`, initialize the root with `index init`
instead of `init`.
## 2) Request Conventions
- Use `X-Amduat-Space: <space_id>` for app isolation.
- Treat graph cursors as opaque tokens (`g1_*`), do not parse.
- Use `as_of` for snapshot-consistent reads.
- Use `include_tombstoned=true` only when you explicitly want retracted facts.
## 3) Core App Flows
### A. High-throughput ingest
Use `POST /v2/graph/batch` with:
- `idempotency_key` for deterministic retries
- `mode=continue_on_error` for partial-apply behavior
- per-item `metadata_ref` or `provenance` for trust/debug
Expect response:
- `ok` (overall)
- `applied` aggregate counts
- `results[]` with `{kind,index,status,code,error}`
### B. Multi-hop retrieval for agents
Primary endpoints:
- `GET /v2/graph/subgraph`
- `POST /v2/graph/retrieve`
- `POST /v2/graph/query` for declarative filtering
Use:
- `as_of` for stable reasoning snapshots
- `max_depth`, `max_fanout`, `limit_nodes`, `limit_edges`, `max_result_bytes`
- provenance filters where needed (`provenance_ref` / `provenance_min_confidence`)
### C. Incremental sync loop
Use `GET /v2/graph/changes`:
- Start with `since_cursor` (or bootstrap with `since_as_of`)
- Persist returned `next_cursor` after successful processing
- Handle `410` as replay-window expiry (full resync required)
- Optional long poll: `wait_ms`
### D. Fact correction
- Edge retraction: `POST /v2/graph/edges/tombstone`
- Node-version retraction: `POST /v2/graph/nodes/{name}/versions/tombstone`
Reads default to exclude tombstoned facts on retrieval surfaces unless `include_tombstoned=true`.
## 4) Endpoint Map (what to use when)
- Write node: `POST /v2/graph/nodes`
- Write version: `POST /v2/graph/nodes/{name}/versions`
- Write edge: `POST /v2/graph/edges`
- Batch write: `POST /v2/graph/batch`
- Point-ish read: `GET /v2/graph/nodes/{name}`
- Edge scan: `GET /v2/graph/edges`
- Neighbor scan: `GET /v2/graph/nodes/{name}/neighbors`
- Path lookup: `GET /v2/graph/paths`
- Subgraph: `GET /v2/graph/subgraph`
- Declarative query: `POST /v2/graph/query`
- Agent retrieval: `POST /v2/graph/retrieve`
- Changes feed: `GET /v2/graph/changes`
- Export: `POST /v2/graph/export`
- Import: `POST /v2/graph/import`
- Predicate policy: `GET/POST /v2/graph/schema/predicates`
- Health/readiness/metrics: `GET /v2/healthz`, `GET /v2/readyz`, `GET /v2/metrics`
- Graph runtime/capability: `GET /v2/graph/stats`, `GET /v2/graph/capabilities`
## 5) Provenance and Policy
Provenance object fields for writes:
- required: `source_uri`, `extractor`, `observed_at`, `ingested_at`, `trace_id`
- optional: `confidence`, `license`
Policy endpoint:
- `POST /v2/graph/schema/predicates`
Key modes:
- predicate validation: `strict|warn|off`
- provenance enforcement: `optional|required`
## 6) Error Handling and Retry Rules
- Retry-safe writes: only retries with same `idempotency_key` and identical payload.
- Validation failures: `400` or `422` (do not blind-retry).
- Not found for references/nodes: `404`.
- Cursor window expired: `410` on `/changes` (rebootstrap sync state).
- Result guard triggered: `422` (`max_result_bytes` or traversal/search limits).
- Internal errors: `500` (retry with backoff).
## 7) Performance and Safety Defaults
Recommended client defaults:
- Set explicit `limit` on scans.
- Always pass `max_result_bytes` on large retrieval requests.
- Keep `max_depth` conservative (start with 2-4).
- Enable `include_stats=true` in development to monitor scanned/returned counts and selected plan.
- Call `/v2/graph/capabilities` once at startup for feature/limit negotiation.
## 8) Minimal Startup Checklist (for external app)
1. Probe `GET /v2/readyz`.
2. Read `GET /v2/graph/capabilities`.
3. Configure schema/provenance policy (`POST /v2/graph/schema/predicates`) if your app owns policy.
4. Start ingest path (`/v2/graph/batch` idempotent).
5. Start change-consumer loop (`/v2/graph/changes`).
6. Serve retrieval via `/v2/graph/retrieve` and `/v2/graph/subgraph`.
7. Monitor `/v2/metrics` and `/v2/graph/stats`.
## 9) Useful Local Helpers
- `scripts/graph_client_helpers.sh` contains practical shell helpers for:
- idempotent batch ingest
- one-step changes sync
- subgraph retrieval
For integration tests/examples:
- `scripts/test_graph_queries.sh`
- `scripts/test_graph_contract.sh`
## 10) Copy/Paste Integration Skeleton
Set local defaults:
```sh
SOCK="amduatd.sock"
SPACE="app1"
BASE="http://localhost"
```
Startup probes:
```sh
curl --unix-socket "${SOCK}" -sS "${BASE}/v2/readyz"
curl --unix-socket "${SOCK}" -sS "${BASE}/v2/graph/capabilities"
```
Idempotent batch ingest:
```sh
curl --unix-socket "${SOCK}" -sS -X POST "${BASE}/v2/graph/batch" \
-H "Content-Type: application/json" \
-H "X-Amduat-Space: ${SPACE}" \
-d '{
"idempotency_key":"app1-batch-0001",
"mode":"continue_on_error",
"nodes":[{"name":"doc:1"}],
"edges":[
{"subject":"doc:1","predicate":"ms.within_domain","object":"topic:alpha",
"provenance":{"source_uri":"urn:app:seed","extractor":"app-loader","observed_at":1,"ingested_at":2,"trace_id":"trace-1"}}
]
}'
```
Incremental changes loop (bash skeleton):
```sh
cursor=""
while true; do
if [ -n "${cursor}" ]; then
path="/v2/graph/changes?since_cursor=${cursor}&limit=200&wait_ms=15000"
else
path="/v2/graph/changes?limit=200&wait_ms=15000"
fi
resp="$(curl --unix-socket "${SOCK}" -sS "${BASE}${path}" -H "X-Amduat-Space: ${SPACE}")" || break
# TODO: parse and process resp.events[] in your app.
next="$(printf '%s\n' "${resp}" | sed -n 's/.*"next_cursor":"\([^"]*\)".*/\1/p')"
[ -n "${next}" ] && cursor="${next}"
done
```
Agent retrieval call:
```sh
curl --unix-socket "${SOCK}" -sS -X POST "${BASE}/v2/graph/retrieve" \
-H "Content-Type: application/json" \
-H "X-Amduat-Space: ${SPACE}" \
-d '{
"roots":["doc:1"],
"goal_predicates":["ms.within_domain"],
"max_depth":2,
"max_fanout":1024,
"limit_nodes":200,
"limit_edges":400,
"max_result_bytes":1048576
}'
```
Subgraph snapshot read:
```sh
curl --unix-socket "${SOCK}" -sS \
"${BASE}/v2/graph/subgraph?roots[]=doc:1&max_depth=2&dir=outgoing&limit_nodes=200&limit_edges=400&include_stats=true&max_result_bytes=1048576" \
-H "X-Amduat-Space: ${SPACE}"
```
Edge correction (tombstone):
```sh
EDGE_REF="<edge_ref_to_retract>"
curl --unix-socket "${SOCK}" -sS -X POST "${BASE}/v2/graph/edges/tombstone" \
-H "Content-Type: application/json" \
-H "X-Amduat-Space: ${SPACE}" \
-d "{\"edge_ref\":\"${EDGE_REF}\"}"
```