---
title: "Clips in a Multi-App Workspace"
description: "How Clips connects to Dispatch and other apps, agent-readable clips, exporting to Brain, CRM call evidence, and natural-language delegation."
---

# Clips in a Multi-App Workspace

Clips is one app among many in a [Dispatch](/docs/template-dispatch) workspace. This page covers what that actually means in practice: how the connection works, and concrete ways other apps and agents can act on your clips or react to what happens with them. See [Clips](/docs/template-clips) for the overview.

## How Clips connects to Dispatch

Whether this is automatic depends on how Clips and Dispatch were set up together, not on whether either one is hosted or running locally.

### Same workspace: automatic

If Clips and Dispatch were generated or added together into one Agent-Native workspace (via `create` or `add-app`) and deployed as one unit, they already share one `.env`, one `A2A_SECRET`, and one workspace registry. Discovery and authenticated A2A calling both just work, with nothing to set up, whether that workspace is running on your machine or in production. This is the expected setup for a real multi-app product built on Clips.

### Separate deployments: one manual step

If Clips and Dispatch are two independently created Agent-Native projects, they don't share a secret and can't call each other yet. Connecting them takes one manual step on each side: add a `remote-agents/<id>.json` resource with a shared secret, from Settings → Agent → Sub-agents (Connect agent), or Dispatch → Agents → Add external agent. See [A2A Protocol](/docs/a2a-protocol) for the full walkthrough.

To check which situation you're in, ask either app's agent "what apps can you see?" If Clips is missing from Dispatch's answer, you're in the second case.

## Integration strategies

### Agent-readable clips

Paste a public Clips share link into an agent, or use **Share → Copy** in the **Share with agents** row for a private clip. Either way, the agent can read the transcript and see key frames without downloading the video, using a link that expires after two hours.

Most agents that can view images handle this on their own, including ChatGPT, Claude Code, Cursor, and Codex. A few text-only chats can read the transcript but not the frames, so open the clip in an image-capable agent for those.

| Endpoint                                                                 | What agents get                                                                                                                      |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `/api/agent-context.json?id=<recordingId>`                               | Clip metadata, transcript status, chapters, CTAs, recommended frames, and links to the transcript/frame APIs                         |
| `/api/agent-transcript.json?id=<recordingId>`                            | Timestamped transcript segments with `startMs`, `endMs`, readable timestamps, text, and optional source labels                       |
| `/api/agent-frame.jpg?id=<recordingId>&atMs=<ms>`                        | A JPEG frame extracted from the video at an original-video timestamp                                                                 |
| `/api/agent-frames.jpg?id=<recordingId>&startMs=<ms>&endMs=<ms>&fps=<n>` | One JPEG contact sheet of up to 36 consecutive frames from a time range, for watching an animation or a transition in a single image |

The endpoints follow the same public/password/expiry rules as the share page, or accept the scoped `agent_access` token from a temporary agent link. Password-protected clips require the password once; successful responses return short-lived tokenized links so downstream agents do not need the plaintext password.

<Endpoint id="doc-block-clips-agent-context" title="Agent context entry point" method="GET" path="/api/agent-context.json" summary="Compact, agent-readable description of a shared clip" auth="Same public / password / expiry rules as the share page, or a scoped agent_access token" params={[
  {
    "name": "id",
    "in": "query",
    "type": "string",
    "required": true,
    "description": "Recording id"
  },
  {
    "name": "agent_access",
    "in": "query",
    "type": "string",
    "required": false,
    "description": "Temporary token from Copy for agent links"
  }
]} responses={[
  {
    "status": "200",
    "description": "Clip metadata, transcript status/failureReason/retryAfterSeconds, agent instructions, and transcript/frame API links"
  }
]}>

Returns clip metadata, transcript status, chapters, CTAs, recommended frames, and links to the transcript and frame APIs. Advertised by public share pages and temporary private agent links so a text- or image-only agent can understand a recording without ingesting raw video.

</Endpoint>

<Endpoint id="doc-block-clips-agent-transcript" title="Timestamped transcript" method="GET" path="/api/agent-transcript.json" summary="Timestamped transcript segments for a shared clip" params={[
  {
    "name": "id",
    "in": "query",
    "type": "string",
    "required": true,
    "description": "Recording id"
  }
]} responses={[
  {
    "status": "200",
    "description": "Transcript status, failureReason, retryAfterSeconds, full text, and segments with startMs, endMs, readable timestamps, text, and optional source labels"
  }
]}>

</Endpoint>

<Endpoint id="doc-block-clips-agent-frame" title="Frame at a timestamp" method="GET" path="/api/agent-frame.jpg" summary="A JPEG frame extracted from the video at an original-video timestamp" params={[
  {
    "name": "id",
    "in": "query",
    "type": "string",
    "required": true,
    "description": "Recording id"
  },
  {
    "name": "atMs",
    "in": "query",
    "type": "integer",
    "required": true,
    "description": "Original-video timestamp in milliseconds"
  }
]} responses={[
  {
    "status": "200",
    "description": "image/jpeg frame"
  }
]}>

</Endpoint>

<Endpoint id="doc-block-clips-agent-frames" title="Frame sheet for a time range" method="GET" path="/api/agent-frames.jpg" summary="Consecutive frames from a time range in one JPEG contact sheet" params={[
  {
    "name": "id",
    "in": "query",
    "type": "string",
    "required": true,
    "description": "Recording id"
  },
  {
    "name": "startMs",
    "in": "query",
    "type": "integer",
    "required": true,
    "description": "Time of the first frame in milliseconds"
  },
  {
    "name": "endMs",
    "in": "query",
    "type": "integer",
    "required": false,
    "description": "End of the range in milliseconds (exclusive); without it, the sheet holds up to 36 frames from startMs, stopping at 60 seconds or the end of the clip"
  },
  {
    "name": "fps",
    "in": "query",
    "type": "number",
    "required": false,
    "description": "Frames per second, up to 60; without it, the video's own frame rate"
  }
]} responses={[
  {
    "status": "200",
    "description": "image/jpeg sheet read left to right, then top to bottom; the X-Clips-Frame-Sheet-Times header lists each cell's time"
  },
  {
    "status": "400",
    "description": "failureKind=request when the range needs more than 36 frames or spans more than 60 seconds; nextStep names a request that fits"
  }
]}>

Cell _i_ shows the frame on screen at `startMs + i × 1000 / fps`. Leave out `fps` to see every frame the video has.

</Endpoint>

If a transcript isn't ready yet, a well-behaved agent waits a bit and retries instead of giving up right away. Long recordings can take a few minutes. If transcription fails because Builder credits ran out, the agent should say so and point to [Transcription and AI metadata](/docs/template-clips-features#transcription-and-ai-metadata).

### Exporting to Brain

Once your workspace connects Brain, Clips sends ready transcripts over automatically after every recording finishes. You can also ask the agent to backfill older recordings, like everything from the last 28 days, instead of waiting for new ones to trickle in. It reports back how many transcripts were exported, skipped, or flagged.

### CRM call evidence

CRM tools sometimes need proof a call happened, without the full recording. Clips hands over just an opaque clip ID and a durable link, never the video or a transcript. This only works for a recording you can already see, and only when you ask for it.

Setting up CRM-to-Clips call automations isn't available yet.

### Natural-language delegation through Dispatch

A sibling app doesn't need a special integration to work with Clips. It can hand Clips' agent a plain-English request, like "find the clip where we discussed pricing," the same way you would in chat, and Clips answers or acts on it directly.

### Staying decoupled

Clips never needs to know Brain's or a CRM's credentials, or vice versa. The `clip.created` event and the agent-readable links sit between apps, so Clips just emits events and answers requests without needing to know who's listening.

## What's next

- [**Clips**](/docs/template-clips) — the overview and what it replaces
- [**Features**](/docs/template-clips-features) — Library, Shared with me, Spaces, and every other feature
- [**Talk to the Agent**](/docs/template-clips-agent) — prompts by task and how the agent sees your screen
- [**Developer Guide**](/docs/template-clips-developers) — quick start, actions, data model, and routes
- [**Dispatch**](/docs/template-dispatch) — the workspace control plane these patterns run under
- [**Automations**](/docs/automations) — declaring an automation that reacts to `clip.created`
- [**A2A Protocol**](/docs/a2a-protocol) — how apps discover, authenticate with, and call each other
- [**Multi-App Workspace**](/docs/multi-app-workspace) — the general pattern of composing first-party apps instead of nesting them
