7 KiB
7 KiB
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:
./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_offor snapshot-consistent reads. - Use
include_tombstoned=trueonly when you explicitly want retracted facts.
3) Core App Flows
A. High-throughput ingest
Use POST /v2/graph/batch with:
idempotency_keyfor deterministic retriesmode=continue_on_errorfor partial-apply behavior- per-item
metadata_reforprovenancefor trust/debug
Expect response:
ok(overall)appliedaggregate countsresults[]with{kind,index,status,code,error}
B. Multi-hop retrieval for agents
Primary endpoints:
GET /v2/graph/subgraphPOST /v2/graph/retrievePOST /v2/graph/queryfor declarative filtering
Use:
as_offor stable reasoning snapshotsmax_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 withsince_as_of) - Persist returned
next_cursorafter successful processing - Handle
410as 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_keyand identical payload. - Validation failures:
400or422(do not blind-retry). - Not found for references/nodes:
404. - Cursor window expired:
410on/changes(rebootstrap sync state). - Result guard triggered:
422(max_result_bytesor traversal/search limits). - Internal errors:
500(retry with backoff).
7) Performance and Safety Defaults
Recommended client defaults:
- Set explicit
limiton scans. - Always pass
max_result_byteson large retrieval requests. - Keep
max_depthconservative (start with 2-4). - Enable
include_stats=truein development to monitor scanned/returned counts and selected plan. - Call
/v2/graph/capabilitiesonce at startup for feature/limit negotiation.
8) Minimal Startup Checklist (for external app)
- Probe
GET /v2/readyz. - Read
GET /v2/graph/capabilities. - Configure schema/provenance policy (
POST /v2/graph/schema/predicates) if your app owns policy. - Start ingest path (
/v2/graph/batchidempotent). - Start change-consumer loop (
/v2/graph/changes). - Serve retrieval via
/v2/graph/retrieveand/v2/graph/subgraph. - Monitor
/v2/metricsand/v2/graph/stats.
9) Useful Local Helpers
scripts/graph_client_helpers.shcontains practical shell helpers for:- idempotent batch ingest
- one-step changes sync
- subgraph retrieval
For integration tests/examples:
scripts/test_graph_queries.shscripts/test_graph_contract.sh
10) Copy/Paste Integration Skeleton
Set local defaults:
SOCK="amduatd.sock"
SPACE="app1"
BASE="http://localhost"
Startup probes:
curl --unix-socket "${SOCK}" -sS "${BASE}/v2/readyz"
curl --unix-socket "${SOCK}" -sS "${BASE}/v2/graph/capabilities"
Idempotent batch ingest:
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):
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:
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:
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):
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}\"}"