Gemini Omni in FiftyOne: A Plugin Your Agent Knows How to Use

Sep 4, 2026
8 min read
Google shipped Gemini Omni for video generation and agentic video understanding for reading footage back. We built both into FiftyOne as one plugin, then shipped skills beside it so the FiftyOne Agent knows when and how to use them. The same pattern works for whatever your team builds.
Every team has something only they need. A model trained on your own data. An internal service that scores samples the way your reviewers do. A validation step your regulator asks for. A vendor API your competitors do not use. None of it ships with any platform, because none of it generalizes past you.

Key takeaways

  • FiftyOne Agent skills are Markdown files shipped inside a FiftyOne plugin that tell the agent when and how to use the plugin's operators.
  • Enabling a plugin makes its operators visible to the FiftyOne Agent immediately, with no retraining or redeploy.
  • The gemini-vision plugin adds Gemini Omni video generation and agentic video understanding to FiftyOne as one plugin with four skills.
  • Gemini video understanding results are written as TemporalDetections, so timestamps are seekable and filterable rather than trapped in a paragraph.
  • On a 30-minute repetitive haystack, static sampling at 0.5 fps matched agentic mode's accuracy at roughly one ninth the token cost.
You can already build that as a FiftyOne plugin, and teams do. What is new is what happens next. The FiftyOne Agent sees your operator the moment the plugin is enabled in your deployment, and can run it. No retraining, no redeploy, nothing to change on the agent side. Your specific, local, unglamorous integration becomes something the agent can reach for.
Being able to run something is not the same as knowing when to. The agent can see your operator exists without knowing which of its options fits the question in front of it, what a run costs, which parameters are safe to guess, or what to do with the result. That gap is what skills close. A skill is a Markdown file you ship inside your own plugin, written by the people who know how the tool should be used, and the agent reads it before acting.
So you are not just handing the agent a new capability. You are handing it your team's judgment about that capability. To show what that looks like end to end, we built something FiftyOne genuinely could not do before: Google's two new video models, generation and understanding, as one plugin with four skills.
Everything here is open source and installable today: https://github.com/AdonaiVera/gemini-vision-plugin
Clips generated by Gemini Omni, sitting in a FiftyOne dataset as ordinary video samples, each carrying the prompt that made it.

A plugin is the tool. A skill is the know how.

What a FiftyOne plugin and a FiftyOne Agent skill each give the agent, and how the agent discovers each one.
What a FiftyOne plugin and a FiftyOne Agent skill each give the agent, and how the agent discovers each one.
What it gives the agentHow the agent gets it
PluginThe ability to do something newOperators appear in list_operators() as soon as the plugin is enabled
SkillKnowing when and how to do it wellSKILL.md files declared in fiftyone.yml, discovered from the manifest
Without the skill, an agent handed a video operator with ten tasks has to guess. With it, the agent reads which phrasing maps to which task, that it should draft at low resolution before spending real money, that generated media must be tagged synthetic so it never slips into a training split, and what to do when a run fails. You are shipping instructions along with the capability.
The rest of this post is one worked example: adding Google's two new video capabilities to FiftyOne, then teaching an agent to drive them.

What we added: Gemini video generation

Gemini Omni became generally available on August 27, 2026. It takes text, images, or video and returns an MP4 with a synthesized audio track. A single generation runs 3 to 10 seconds and can be extended in 10 second steps up to 40 seconds. Drafts render at 360p for roughly a third of the cost of 720p, and finals upscale to 4K.
The plugin exposes six tasks, picked by what you are starting from:
The six Gemini Omni generation tasks in the plugin, what each starts from, and what you need selected in FiftyOne to run it.
The six Gemini Omni generation tasks in the plugin, what each starts from, and what you need selected in FiftyOne to run it.
TaskStarting fromSelection
text_to_videoa descriptionnone
image_to_videoone image to animate1 image
first_last_framea start and an end frame2 images
reference_to_videosubjects to keep consistent1 to 3 images
edita clip the plugin generated1 generated video
extenda clip the plugin generated1 generated video
The six generation tasks, each labelled with what it needs selected.
The generated clip is not a file you download and lose track of. It is added to your dataset as a video sample carrying the prompt that produced it, the task used, the model, the resolution, and the IDs of the samples it drew on.

The interaction ID is the feature

One field on that sample matters more than the rest: gemini_interaction_id.
Omni's editing is stateful. You do not send it a video and a diff. You resume the interaction that produced the video and describe what should change, and the model keeps everything you did not mention. That is the difference between iterating on a shot and rolling the dice again with a longer prompt.
So the plugin stores that id on the sample. A clip generated on Monday is still editable on Wednesday, by anyone with access to the dataset, because the handle to the model's own state travels with the data:
Those two calls turned a daylight warehouse into a night shot, then turned a 10 second clip into 20. Each result is itself editable, so a session converges on a shot over several turns instead of restarting.
The honest limit: this only works on clips the plugin generated. Footage you imported has no interaction to resume, and the operator says so plainly instead of failing in a confusing way.
The generation operator. Draft at 360p, then re render once the shot is right.

What we added: reading video back as data

The other direction is agentic video understanding, where the model navigates the timeline itself rather than being handed a fixed strip of frames.
Here the design decision that mattered has nothing to do with the model. Ask any vision language model what happens in a video and you get a paragraph. You cannot filter a paragraph, sort by it, or seek to it. So instead of asking Gemini to describe what it found, each task asks for a JSON schema of timestamped events: start, end, label, description, confidence.
Structured timestamps become TemporalDetections, written straight onto the video sample, where they render as segments on the App timeline and filter like any other label. Eight of the ten tasks work this way.
Gemini's answers as temporal detections, seekable in the timeline and filterable in the sidebar.
That last line matters more than the number. Almost every disagreement about a count is really a disagreement about what counts as one, so we ask the model to state its rule and put it in front of the user.

How the FiftyOne Agent finds plugin skills

Everything above is an operator, and an operator is only useful to someone who knows it exists. That is the same problem an agent has.
FiftyOne plugins can ship skills: Markdown workflow guides declared in the plugin's own manifest. The FiftyOne Agent discovers them from the manifest as soon as the plugin is enabled. There is no registration step and nothing to change on the agent's side.
It is two things. A declaration in fiftyone.yml:
And a SKILL.md https://docs.voxel51.com/agents/developing_skills.html per skill, with frontmatter the agent reads:
The body is not documentation. It is operating instructions: which task to pick from which phrasing, how to bound the cost, what to do with the result, and what the failure modes look like.
One mechanism is worth calling out. The agent parses each skill's operator table and reads a Requires Prompt column. Operators marked False it may run directly. Operators marked True always surface their parameters first, so the user can review and edit before anything runs or bills. Every operator in this plugin is marked True, because each call costs money.

The agent using it

With the plugin enabled, this is a complete instruction:
How many distinct vehicles are in this clip?
Nothing in that sentence names an operator, a task, or a parameter. The agent finds the skill from the plugin's manifest, reads that counting is what the count task does, and assembles the call itself.
The agent resolves a plain question to the right operator and task, on the user's current selection.
Read what it proposes closely. It picked the count task, wrote a prompt spelling out its own counting rule, named a label field, and set a thinking level and a one video cap. The user specified none of that.
The proposed call, surfaced for review before anything runs or bills.
This is the part that only works because of the skill. A bare operator gives the agent a button. The skill is what tells it which of the ten tasks fits the question, to bound the run to one video, and to write a descriptive label field so results stay findable later.
And the result lands as data, not as a chat message:
armored_truck [1, 120], silver_car [1, 31], white_suv [60, 120]. The answer as temporal detections on the sample, seekable and filterable.
Point the same agent at generation and the other skill takes over. Here it generated a warehouse clip with Omni and tagged it synthetic without being asked, because the skill instructs that so a generated sample never drifts into a training split unmarked. It also reported honestly when one of its two background jobs did not produce the sample it expected.
Generation running as background jobs, the clip tagged synthetic, and the agent flagging its own failed run rather than claiming success.

What we measured

On the understanding side we did not want to repeat Google's efficiency figures, so we built a test where the right answer is checkable. Clips from FiftyOne's quickstart-video dataset were concatenated into one long video, with the single clip containing an armored truck inserted exactly once at a known offset. Then the same question, of the same video, under four processing configurations.
On the 30 minute version, at 163 MB, uploaded through the Files API:
Four processing configurations on the same 30-minute needle-in-a-haystack video (163 MB, Files API). Static 0.5 fps found the target at roughly one ninth the tokens of agentic high.
Four processing configurations on the same 30-minute needle-in-a-haystack video (163 MB, Files API). Static 0.5 fps found the target at roughly one ninth the tokens of agentic high.
ConfigurationTokensVideo lookupsSecondsFound the truck
Agentic, thinking_level="high"553,56018145.8yes, exactly
Agentic, thinking_level="low"274,1831672.3no, missed it
Static, fps=1119,184017.8yes, exactly
Static, fps=0.561,053015.5yes, exactly
The cheapest run was also exactly right. The second most expensive was the only one that missed.
Two findings, neither of them what we expected. Agentic mode has a cost floor, because the loop spends tokens deciding where to look before it looks. On footage that a uniform pass already handles, static sampling at half a frame per second was roughly nine times cheaper and returned the same timestamps to the second. And thinking_level low cost us recall, not just latency. On the long video it was the only configuration that missed a target the other three found exactly.
The caveat is real. Our haystack is visually repetitive by construction, which is close to the best case for uniform sampling. Google's figures are for long, varied content where most of the timeline is genuinely irrelevant. We have not refuted them. We have established that they are not automatic. So the plugin ships both modes, puts this benchmark in the skill the agent reads, and tells you to try static first.

Building your own FiftyOne Agent skill

If you take one thing from this, take the shape rather than the integration. Any capability you can reach from Python can become an operator, and any operator can become something your agent uses well:
  • Write the operator. Whatever your team already does by hand. It shows up in the agent's tool list the moment the plugin is enabled.
  • Return data, not prose. Ask your model for a schema and write real FiftyOne labels. An answer you can filter is worth more than a paragraph you have to re read.
  • Ship a SKILL.md beside it. Say when to use it, how to keep it cheap, what to do with the result, and how it fails. This is the part that turns a button into judgment.
  • Decide what the agent may do alone. The Requires Prompt column is where you draw that line, and it is worth thinking about before your agent spends money for you.

Try it

Three commands, then you are talking to it:
Open the agent panel, select a video, and ask in plain language. You never name an operator, a task, or a parameter:
  • How many distinct vehicles are in this clip?
  • Find every time a pedestrian appears in these videos
  • Why does the car slow down?
  • Pull the best frames out of this video
  • Generate a clip of a forklift in a warehouse, then make it night time
The agent reads the skills, picks the task, shows you the call it intends to make, and waits. You approve or edit it. The answer comes back as labels on your samples, not as text in a chat window that you have to copy somewhere useful.
That last prompt is the one to try if you only try one. It is two tasks in one sentence, and a naive agent generates twice. This one generates once, then edits what it made, because the skill tells it that editing preserves the shot you already liked.
The operators, the four skills, and the schemas behind them are all here: https://github.com/AdonaiVera/gemini-vision-plugin. Fork it, swap Gemini for whatever your team already uses, and your agent picks up the new tool the moment you enable the plugin.

FAQ

Talk to an AI expert

Loading related posts...