> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uselamina.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Recipes

> End-to-end recipes for agents that plan, approve, execute, monitor, cancel, and reuse creative work with Lamina MCP v2.

## What Agents Should Prefer

Interactive agents should start with:

```text theme={null}
https://app.uselamina.ai/mcp/agent/v2
```

The v2 surface has seven task-level tools and can stitch apps, atomic models, and composition into a
single stored plan. Use the 30-tool advanced endpoint at `https://app.uselamina.ai/mcp/agent` only
for direct control or operations v2 does not expose.

## Recipe 1: Plan, Approve, Execute

<Steps>
  <Step title="Check credits">
    Call `lamina_credits` and surface the current balance before paid generation.
  </Step>

  <Step title="Plan">
    Call `lamina_plan` with the creative brief and known inputs. Planning does not dispatch
    generation.
  </Step>

  <Step title="Clarify">
    If `status` is `needs_clarification`, ask every returned question and call `lamina_plan` again
    with the clarified brief or inputs. For `awaiting_approval`, collect `requiredInputs[]` answers
    for execution without changing the frozen plan.
  </Step>

  <Step title="Approve">
    Show the plan's steps, outputs, warnings, and estimated credits. Ask the user to approve both
    the work and a finite maximum credit budget.
  </Step>

  <Step title="Execute">
    Call `lamina_execute` with the exact `planId` and `planFingerprint`, the collected inputs,
    `maxCredits`, and an idempotency key.
  </Step>

  <Step title="Wait">
    Call `lamina_status` with the returned `runId` and `wait=true`. Repeat status when the run
    remains non-terminal or the wait reports `timedOut: true`.
  </Step>

  <Step title="Deliver">
    Return completed `outputs[]` URLs and their media types. Never treat `queued` or `running` as
    success.
  </Step>
</Steps>

Example plan call:

```json theme={null}
{
  "tool": "lamina_plan",
  "arguments": {
    "brief": "Create a cinematic Instagram launch image for a premium running shoe.",
    "platform": "instagram",
    "modality": "image",
    "inputs": {
      "productImage": "https://example.com/shoe.png"
    },
    "maxEstimatedCredits": 80
  }
}
```

Illustrative approval-ready response:

```json theme={null}
{
  "status": "awaiting_approval",
  "planId": "99ebc7c6-24f3-4fc2-9d53-2e3f49f3bec1",
  "planFingerprint": "<fingerprint>",
  "steps": [
    {
      "id": "hero",
      "kind": "app",
      "summary": "Generate the product hero image"
    }
  ],
  "requiredInputs": [],
  "estimatedCredits": 60,
  "warnings": []
}
```

After explicit approval:

```json theme={null}
{
  "tool": "lamina_execute",
  "arguments": {
    "planId": "99ebc7c6-24f3-4fc2-9d53-2e3f49f3bec1",
    "planFingerprint": "<fingerprint>",
    "inputs": {
      "productImage": "https://example.com/shoe.png"
    },
    "maxCredits": 80,
    "idempotencyKey": "shoe-launch-image-v1"
  }
}
```

## Recipe 2: Clarification Without Plan Drift

There are two kinds of questions:

* `questions[]` with `status: "needs_clarification"` means the planner cannot freeze a safe plan.
  Ask the questions, then plan again with the answer.
* `requiredInputs[]` with `status: "awaiting_approval"` belongs to the frozen plan. Collect those
  values and pass them to `lamina_execute`; do not call `lamina_plan` again.

This distinction preserves the plan the user reviewed and approved.

## Recipe 3: Multi-Step Image and Video

Ask Lamina to stitch the workflow rather than manually copying one step's output URL into the next:

```json theme={null}
{
  "tool": "lamina_plan",
  "arguments": {
    "brief": "Create a 4:5 product hero image, then animate it into a five-second 9:16 launch clip.",
    "modality": "video",
    "platform": "instagram-reels",
    "inputs": {
      "productImage": "https://example.com/product.png"
    },
    "preferredPath": "auto",
    "maxEstimatedCredits": 150
  }
}
```

The frozen plan contains the binding between steps. Preserve it through execution; do not
rediscover apps or re-plan after approval.

## Recipe 4: Brand-Aware Planning

Call brand context first:

```json theme={null}
{
  "tool": "lamina_brand_context",
  "arguments": {}
}
```

Use the returned `brandProfileId` in `lamina_plan`. Empty brand fields mean the workspace has not
configured them—never invent voice, colors, guardrails, or performance claims.

If the OAuth token lacks brand-read permission, planning continues without brand context and returns
a warning. Reauthorize if brand grounding is required.

## Recipe 5: Upload a Local Asset

Request a signed upload:

```json theme={null}
{
  "tool": "lamina_upload_asset",
  "arguments": {
    "filename": "product-front.png",
    "mediaType": "image"
  }
}
```

PUT the file bytes to `uploadUrl` using the returned content type. Only after the upload succeeds
should the agent use `assetUrl` in planning or execution. The MCP tool does not upload bytes itself.

## Recipe 6: Poll and Cancel Reliably

Status request:

```json theme={null}
{
  "tool": "lamina_status",
  "arguments": {
    "runId": "<run-id>",
    "wait": true,
    "timeoutSeconds": 25
  }
}
```

The same tool accepts pipeline, app-workflow, atomic image/video, and compose IDs. A wait that times
out returns the latest snapshot; it does not mean the run failed.

Cancellation request:

```json theme={null}
{
  "tool": "lamina_cancel",
  "arguments": {
    "runId": "<run-id>"
  }
}
```

Cancellation is idempotent and provider-dependent. Report `cancel_requested` as a request, not as
confirmed cancellation. A `not_cancellable` response is also not `cancelled`.

## Recipe 7: Use an Advanced App Directly

Use the advanced endpoint only when the user requests direct app control:

```text theme={null}
lamina_discover
  → lamina_describe
  → approval
  → lamina_run
  → lamina_status
```

Key `inputs` by the stable parameter keys returned from `lamina_describe`. Use only returned option
labels. The advanced `lamina_create` tool is a compatibility name over the same frozen planner;
legacy mode=`app` callers may still dispatch with `lamina_run`, but dynamic workflows, route
choices, and bounded execution should use the v2 plan lifecycle.

## Recipe 8: SDK or REST Agent

Server-side agents that own an API key can use `@uselamina/sdk` or `/v1`. Their output contract is
the REST contract, where workflow output values are read from `outputs[].value`:

```ts theme={null}
import { LaminaClient } from '@uselamina/sdk';

const client = LaminaClient.fromEnv();
const planned = await client.content.plan({
  brief: 'Create a premium Instagram launch visual for a running shoe.',
  platform: 'instagram',
  modality: 'image',
});

if (planned.data.canonicalStatus !== 'awaiting_approval') {
  console.log(planned.data.questions, planned.data.alternatives);
  process.exit(0);
}

const started = await client.content.execute(planned.data.planId, {
  planFingerprint: planned.data.planFingerprint,
  inputs: {},
  maxCredits: planned.data.estimatedCredits ?? 25,
  allowUnknownCost: planned.data.estimatedCredits == null,
  idempotencyKey: 'launch-visual-001',
});

const result = await client.content.status(started.data.runId);
console.log(result.data.status, result.data.result);
```

Do not mix REST `outputs[].value` examples with v2 MCP status, which returns normalized
`outputs[].url`.

## Smoke Test Checklist

1. Install `https://app.uselamina.ai/mcp/agent/v2`.
2. Complete OAuth and choose a workspace.
3. Confirm the client lists the task-level plan/choose/execute/status lifecycle tools.
4. Call `lamina_credits`.
5. Call `lamina_plan` with a simple image brief.
6. Resolve `questions[]` or `requiredInputs[]` without guessing.
7. Display the frozen plan and estimated cost, then obtain approval.
8. Call `lamina_execute` with a budget and idempotency key.
9. Call `lamina_status` until terminal.
10. Confirm completed outputs include usable URLs.
11. Exercise `lamina_cancel` on a test run where safe.

## Troubleshooting

* `authorization_required`: start OAuth from the MCP client or reinstall the hosted server.
* `insufficient_scope`: reconnect and approve the required scope.
* `needs_clarification`: ask the returned planning questions and plan again.
* `plan_expired`: build and approve a new plan.
* `plan_fingerprint_mismatch`: execute the exact stored fingerprint; do not alter it.
* `unknown_cost_requires_approval`: display the warning and request explicit permission before
  setting `allowUnknownCost: true`.
* status wait timed out: call `lamina_status` again with the same run ID.
* terminal failure: surface the returned code and message; do not silently switch apps or models.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.