[agent] Opt-in TwelveLabs video understanding (analyze_video tool)#198
[agent] Opt-in TwelveLabs video understanding (analyze_video tool)#198mohit-twelvelabs wants to merge 5 commits into
Conversation
Adds a TwelveLabs Pegasus integration behind an optional API key. With no key set, behavior is unchanged. - TwelveLabsClient: Pegasus video understanding over the v1.3 REST API via URLSession (no official Swift SDK). Mirrors AnthropicClient's auth/error shape; the key lives in the Keychain via TwelveLabsKeychain, never hardcoded. - analyze_video agent tool (also exposed over MCP): ask Pegasus a question about a whole video clip — summary, content check, locate a moment — reasoning over motion and audio together, beyond inspect_media's on-device frame sampling. Returns a clear notice and no-ops when no key is configured. - Settings → Agent: TwelveLabs API key field, stored exactly like the Anthropic key (Keychain, DEBUG env override). - README + agent instructions document the opt-in capability.
Mirror inspect_media's generationStatus handling so a missing video file with a .failed status reports the failure message instead of a generic 'Media file not on disk'.
|
Good catch from Cursor Bugbot 🐛 — fixed in — Mohit (@mohit-twelvelabs, TwelveLabs) |
- uploadAsset now writes the multipart body to a temp file and uses URLSession.upload(fromFile:), streaming the source clip in 1 MiB chunks instead of loading the whole (multi-GB) video into memory. - Set a 300s timeoutInterval on the upload and analyze requests so whole-clip Pegasus analysis doesn't hit URLSession's default 60s limit.
|
Thanks Cursor Bugbot 🐛 — both addressed in
— Mohit (@mohit-twelvelabs, TwelveLabs) |
…-upload limit - analyze_video now runs client.understand in a detached task so the synchronous multipart-body streaming never blocks the @mainactor editor. - uploadAsset rejects files over TwelveLabs' 200MB direct-upload limit with a clear, actionable error instead of an opaque API failure. (Larger files need the multipart/chunked upload flow — a follow-up.)
|
Thanks again, Cursor Bugbot 🐛 — both addressed in
— Mohit (@mohit-twelvelabs, TwelveLabs) |
…ctually fires attributesOfItem(.size) returns an NSNumber; the as? Int cast is unreliable (notably under non-Apple Foundation), which could let the fileTooLarge guard silently no-op. URL.resourceValues(.fileSizeKey).fileSize returns Int directly.
|
Good catch, Cursor 🐛 — fixed in — Mohit (@mohit-twelvelabs, TwelveLabs) |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 30bd1e3. Configure here.
| // source file from disk, which would otherwise block the editor on @MainActor. | ||
| answer = try await Task.detached(priority: .userInitiated) { | ||
| try await client.understand(videoURL: url, prompt: prompt) | ||
| }.value |
There was a problem hiding this comment.
Cancel leaves upload running
Medium Severity
analyze_video runs TwelveLabsClient.understand inside Task.detached, so stopping the agent (or cancelling the stream task) does not stop the in-flight upload and analyze. The editor may treat the tool as cancelled while the clip still streams to TwelveLabs and completes analysis.
Reviewed by Cursor Bugbot for commit 30bd1e3. Configure here.
|
@mohit-twelvelabs can you shoot us an email at founders@palmier.io about this. we want to chat |
|
someone from our team will be in contact, thanks! |


Hi! I'm Mohit, I work at TwelveLabs (@mohit-twelvelabs).
Palmier Pro is "the video editor built for AI," so I added an optional bridge to TwelveLabs Pegasus — a cloud video-understanding model that reasons over a whole clip's visuals and audio at once. It's entirely opt-in: with no key set, nothing changes.
What it adds
TwelveLabsClient(Agent/Clients/) — Pegasus video understanding over the v1.3 REST API viaURLSession. There's no official Swift SDK, so it talks to the API directly. It mirrorsAnthropicClient's auth/error shape, and the key lives in the macOS Keychain viaTwelveLabsKeychain(mirroringAnthropicKeychain, including the#if DEBUGenv override) — never hardcoded.analyze_videoagent tool (Agent/Tools/, wired intoToolExecutor/ToolDefinitionsexactly like the existing tools, so it's also exposed over the MCP server) — the in-app agent can ask Pegasus about a video asset: "summarize this clip," "what is the speaker demonstrating," "find the moment the goal is scored." This complementsinspect_media(on-device sampled frames + transcription) by adding whole-clip understanding that isolated frames miss. If no TwelveLabs key is configured, the tool returns a clear notice and no-ops, so the agent simply falls back toinspect_media.Why it fits
A video editor built for AI is the ideal home for video understanding. This keeps the existing on-device path as the default and layers cloud understanding on top only when a user provides their own key.
How it was tested
api.twelvelabs.io/v1.3: multipart asset upload (method=direct,file=) →_id, thenPOST /v1.3/analyzewith{"video":{"type":"asset_id",...},"model_name":"pegasus1.5","stream":false}returning the answer at.data.ToolExecutorextension pattern,AppTheme-only styling in the settings pane, minimal comments per AGENTS.md, async/await + off-main-actor file IO). New files passswiftc -parse.swift buildto completion on my non-macOS-26 CI — the build reached the Metal-toolchain plugin step (theMetalCIKernelPlugin) before my toolchain blocked there, which is unrelated to these changes. CI here runs on amacos-26runner and will compile it properly; I'd appreciate a maintainer building it on macOS to confirm. Happy to adjust anything to fit your conventions.You can grab a free API key at https://twelvelabs.io — there's a generous free tier.
Note
Medium Risk
Uploads user video to a third-party API when enabled; key handling follows existing Anthropic patterns but adds new external dependency and long-running network I/O on agent tool calls.
Overview
Adds optional cloud video understanding via TwelveLabs Pegasus. With no API key, behavior is unchanged.
TwelveLabsClientuploads a local video to TwelveLabs v1.3 (streaming multipart to disk, 200 MB direct-upload cap, 300s timeouts), runs Pegasuspegasus1.5, and returns the answer.TwelveLabsKeychainstores the key like Anthropic (Keychain + DEBUG env override).New
analyze_videoagent/MCP tool (mediaRef+prompt) validates video assets on disk, runs upload/analysis off the main actor, and returns a clear notice when TwelveLabs isn’t configured so the agent falls back toinspect_media.Settings → Agent gets a TwelveLabs key field (save/remove, masked display). README and agent instructions document when to use
analyze_videovs on-device inspection.Reviewed by Cursor Bugbot for commit 30bd1e3. Bugbot is set up for automated code reviews on this repo. Configure here.