Driftstack DRIFTSTACK docs
Docs

Recipes

A recipe is an immutable snapshot of a finished agent-session — the structured intent_log plus the full transcript at the moment of capture. Recipes let customers replay the same flow later without re-paying the LLM decompose cost.

The v1.0 surface covers create, list, read, and delete: POST /v1/recipes, GET /v1/recipes, GET /v1/recipes/{id}, and DELETE /v1/recipes/{id}. Recipe execution — replaying a recipe against a new agent-session — lands at v1.1 (D2/D3 scope per the v2-#37 queue).

Resource shape

{
  "id": "rec_<uuid>",
  "account_id": "<account-uuid>",
  "agent_session_id": "agt_<uuid> | null",
  "label": "my checkout flow",
  "description": "Snapshot of the example.com checkout session.",
  "intent_count": 12,
  "created_at": "<ISO-8601>",
  "updated_at": "<ISO-8601>"
}

agent_session_id is null when the originating agent-session has been deleted (ON DELETE SET NULL — the recipe survives the source session’s lifecycle). intent_count is the length of the flattened intent_log. The list endpoint omits the intent array for payload weight; fetch a single recipe with GET /v1/recipes/{id} to get the full replayable intent_log.

Create

POST /v1/recipes

Request body:

{
  "agent_session_id": "agt_<uuid>",
  "label": "my checkout flow",
  "description": "Snapshot of the example.com checkout session."
}
  • agent_session_id — required. Must belong to the calling account; cross-account references return 404.
  • label — required. 1-120 characters after trim.
  • description — optional. Up to 2000 characters.

Response 201 Created returns the resource above.

List

GET /v1/recipes

Lists the calling account’s recipes, newest first. Cursor-paginated:

  • limit — optional. 1-100, defaults to 50.
  • cursor — optional. Opaque cursor from a prior page’s next_cursor.

Response 200 OK:

{
  "data": [],
  "has_more": true,
  "next_cursor": "<opaque> | null"
}

Each data entry is the resource shape above without the intent_log array — list items carry only intent_count for payload weight. Fetch a single recipe to get the replayable intents. next_cursor is null on the last page.

Get one

GET /v1/recipes/{id}

Returns a single recipe in full, including the replayable intent_log array (the list endpoint omits it). A non-existent id — or one belonging to another account — returns 404; the server doesn’t distinguish missing from forbidden, to avoid leaking existence.

Delete

DELETE /v1/recipes/{id}

Deletes a recipe. Response 204 No Content. A non-existent id — or one belonging to another account — returns 404, the same anti-enumeration contract as the rest of the customer surface. Delete is not idempotent: deleting an already-deleted recipe returns 404, not 204.

Intent log assembly

When the route fires, the server walks the source agent-session’s transcript and flatMaps every plan-executed agent turn’s structured intents array into a single intent_log. The result is captured atomically (insert-once; never edited) so the historical snapshot survives any later session activity.

Operator + user transcript entries don’t carry intents — only agent turns from a successful decompose+execute step contribute. A session that ran exclusively in mode='manual' will produce a recipe with intent_count: 0 (because manual sessions log operator entries, not decomposer plans). That’s expected — the recipe is still useful as a transcript-only snapshot.

Errors

StatusTypeWhen
400validationbody fails schema (missing label, label > 120 chars, description > 2000)
404not-foundagent_session_id doesn’t exist or belongs to another account
401unauthorizedmissing or invalid bearer token
503feature-unavailableactivation gate off (recipe library or agent-sessions repo not wired)

Upcoming (v1.1)

  • POST /v1/recipes/{id}/execute — replay a recipe against a new agent-session, skipping the decompose step

This ships in the v1.1 D2/D3 scope per the Driftstack design verdict on the v2-#37 queue.