> ## 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 create, monitor, clarify, and reuse creative work with Lamina.

## What Agents Should Prefer

For interactive agents, prefer hosted MCP:

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

For server-side agents, use the SDK or REST API with `LAMINA_API_KEY`. Hosted MCP and REST share the
same runtime model: create work, preserve `runId`, wait or subscribe to completion, inspect typed
outputs, and reuse final artifacts explicitly.

## Recipe 1: Hosted MCP Creative Run

After installing Lamina MCP in Claude Code, Codex, Cursor, or another MCP client, use this flow:

<Steps>
  <Step title="Create">
    Call `lamina_create` with `brief`, `platform`, and `modality`.
  </Step>

  <Step title="Clarify if needed">
    If the response status is `needs_input`, ask the user for the listed missing fields and call
    `lamina_create` again with those values in `inputs`.
  </Step>

  <Step title="Wait">
    Call `lamina_status` with `runId` and `wait=true`.
  </Step>

  <Step title="Reuse">
    Inspect each output's `type`, `status`, and `value`. Reuse completed asset URLs as explicit
    references in the next Lamina run.
  </Step>
</Steps>

Example MCP call:

```json theme={null}
{
  "tool": "lamina_create",
  "arguments": {
    "brief": "Create a cinematic launch image for a premium running shoe.",
    "platform": "instagram",
    "modality": "image"
  }
}
```

Expected started response:

```json theme={null}
{
  "runId": "99ebc7c6-24f3-4fc2-9d53-2e3f49f3bec1",
  "status": "queued",
  "workflowName": "Product Hero Image",
  "selectedApp": {
    "name": "Product Hero Image",
    "whyMatched": "Matches image launch creative intent"
  }
}
```

Expected clarification response:

```json theme={null}
{
  "runId": null,
  "status": "needs_input",
  "needsInput": {
    "message": "This workflow needs additional inputs before Lamina can start the run.",
    "missing": [
      {
        "name": "Product Image",
        "type": "url",
        "accept": ["image"]
      }
    ],
    "suggestedPrompt": "Ask the user for Product Image."
  }
}
```

## Recipe 2: TypeScript Agent With SDK

Use this for Node.js agents, backend workers, and agent runtimes that own their own API key.

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

const client = LaminaClient.fromEnv();

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

if (created.data.needsInput || !created.data.runId) {
  console.log(created.data.needsInput?.missing);
  console.log(created.data.needsInput?.suggestedPrompt);
  process.exit(0);
}

const result = await client.runs.wait(created.data.runId, {
  timeoutMs: 120_000,
  intervalMs: 4_000,
});

for (const output of result.data.outputs) {
  if (output.status === 'completed') {
    console.log(output.type, output.value);
  }
}
```

Full example:

```text theme={null}
examples/agents/typescript/creative-agent-recipe.ts
```

## Recipe 3: Python Agent With REST

Use this when the agent is written in Python or runs in an environment without the TypeScript SDK.

```python theme={null}
created = request(
    "/v1/content/create",
    method="POST",
    body={
        "brief": "Create a cinematic launch image for a premium running shoe.",
        "platform": "instagram",
        "modality": "image",
    },
)

if created["data"].get("needsInput") or not created["data"].get("runId"):
    print(created["data"].get("needsInput", {}).get("missing", []))
    raise SystemExit(0)

status = wait_for_run(created["data"]["runId"])
```

Full example:

```text theme={null}
examples/agents/python/creative_agent_recipe.py
```

## Recipe 4: Brand-Aware Planning

Agents should call brand context before generating when the user asks for brand-safe, campaign-safe,
or performance-aware content.

```ts theme={null}
const brand = await client.intelligence.getBrandContext({
  platform: 'instagram',
  modality: 'image',
  objective: 'launch campaign',
});

console.log(brand.data.brandDna?.guardrails ?? []);
console.log(brand.data.guidance?.promptDirectives ?? []);
```

For MCP clients, use `lamina_brand` before `lamina_create` when the agent needs explicit voice,
visual, guardrail, or winning-pattern context.

## Recipe 5: Artifact Reuse

Agents should not scrape provider-specific payloads. Treat completed outputs with string `value`
fields as reusable artifact URLs.

```ts theme={null}
const artifacts = result.data.outputs
  .filter((output) => output.status === 'completed' && typeof output.value === 'string')
  .map((output) => ({ type: output.type, url: output.value }));

if (artifacts[0]) {
  await client.content.create({
    brief: 'Create a matching story variant using this reference.',
    platform: 'instagram-story',
    modality: artifacts[0].type,
    inputs: {
      Reference: artifacts[0].url,
    },
  });
}
```

## Smoke Test Checklist

Run this checklist for every supported MCP client before broad distribution:

1. Install `https://app.uselamina.ai/mcp/agent`.
2. Complete OAuth and choose a workspace.
3. Confirm the client lists the Lamina tools.
4. Call `lamina_discover` for an image or video launch brief.
5. Call `lamina_create` with a simple brief.
6. If `needs_input` is returned, provide the missing input and retry.
7. Call `lamina_status` with `wait=true`.
8. Confirm completed outputs include typed values the agent can reuse.
9. Remove or revoke the client after testing if it used a temporary workspace.

## Troubleshooting

* `authorization_required`: start OAuth from the MCP client or reinstall the hosted server.
* `insufficient_scope`: reconnect and approve the requested scope.
* `needs_input`: ask the user for the listed missing field; do not start a run with guessed data.
* `failed`: surface `errorMessage` and output-level errors; do not blindly retry invalid inputs.
* Timeout while waiting: call `lamina_status` again with the same `runId`.
