Memory Writes
The write primitive. Append a typed memory entry to a customer’s
ledger. Three types: decision, action, observation. Idempotent
when you supply idempotency_key. Backed by MCP tool write_memory.
The ledger feeds the next GET /v1/context call as recent_decisions
plus internal signal computation. This is how agents share state across
sessions, runs, and even across separate agents.
Request
POST /v1/memory
| Field | Type | Notes |
|---|---|---|
customer | string, required | Customer ID. Get one from /v1/context. |
type | enum, required | decision, action, or observation. |
agent | string, required | Agent identifier you control. Pick a stable slug. |
payload | object, required | Free-form. Recommend keeping under 4 KB. |
idempotency_key | string, optional | Same key + same payload returns the original entry instead of creating a new one. |
Required scope: memory:write.
When to use which type
decision. The agent picked a path. (“escalate_to_human”, “send_followup_email”)action. The agent did a thing in the world. (“sent_email”, “created_ticket”, “placed_call”)observation. The agent noticed something worth recording but did not act. (“customer_mentioned_competitor”)
Examples
curl
curl https://api.waypath.app/v1/memory \
-H "X-API-Key: wp_live_..." \
-H "Content-Type: application/json" \
-d '{
"customer": "cus_8af2",
"type": "decision",
"agent": "support_v2",
"payload": {
"action": "escalate_to_human",
"reason": "customer_frustrated",
"confidence": 0.86
},
"idempotency_key": "esc-1284-v2"
}'node-fetch
const res = await fetch('https://api.waypath.app/v1/memory', {
method: 'POST',
headers: {
'X-API-Key': process.env.WAYPATH_API_KEY!,
'Content-Type': 'application/json',
},
body: JSON.stringify({
customer: 'cus_8af2',
type: 'decision',
agent: 'support_v2',
payload: { action: 'escalate_to_human', reason: 'customer_frustrated' },
idempotency_key: 'esc-1284-v2',
}),
})
const entry = await res.json()python
import os, requests
entry = requests.post(
'https://api.waypath.app/v1/memory',
headers={'X-API-Key': os.environ['WAYPATH_API_KEY']},
json={
'customer': 'cus_8af2',
'type': 'decision',
'agent': 'support_v2',
'payload': {'action': 'escalate_to_human', 'reason': 'customer_frustrated'},
'idempotency_key': 'esc-1284-v2',
},
timeout=5,
).json()MCP
await mcp.tools.write_memory({
customer: 'cus_8af2',
type: 'decision',
agent: 'support_v2',
payload: { action: 'escalate_to_human' },
idempotency_key: 'esc-1284-v2',
})Response
{
"id": "mem_a91b",
"customer": "cus_8af2",
"type": "decision",
"ts": "2026-04-29T18:14:32Z",
"idempotency_key": "esc-1284-v2"
}Idempotency
The pattern is: build a deterministic key from the inputs that should be safe to replay. Examples:
- A ticket escalation:
esc-{ticketId}-{version} - A scheduled outbound:
out-{customerId}-{cadenceWindow} - A backfill row:
import-{sourceSystem}-{rowId}
Replays with the SAME idempotency_key and SAME payload return the
original entry with status 201 and the original ts. Replays with the
same key but DIFFERENT payload return 409 idempotency_conflict. Pick
a fresh key for genuinely new writes.
Errors
| Status | Code | Cause |
|---|---|---|
| 400 | invalid_payload | Missing required field, or type not in enum. |
| 401 | unauthenticated | Missing or invalid X-API-Key. |
| 403 | forbidden_scope | Key lacks memory:write. |
| 404 | not_found | Customer ID does not exist. |
| 409 | idempotency_conflict | Same idempotency_key, different payload. |
| 429 | rate_limited | Per-key cap. Honor Retry-After. |