Replicate's predictions API (run any model) → the Naive images + video primitives
Replicate is a trademark of its respective owner, used here for identification and migration comparison only. No endorsement, partnership, or affiliation is implied.
predictions.create
submits a job, predictions.get polls it, and a webhook fires on completion. It does this exceptionally
well across thousands of community and official models — FLUX for images, Kling/Minimax for video,
plus LLMs, upscalers, and your own fine-tunes. But when the thing generating the media is an
agent that also holds cards, an inbox, a phone number, and a KYC’d identity, a Replicate account is
a disconnected vendor account:
- Generation lives behind a Replicate API token (
r8_...) — a credential that exists only inside Replicate, unrelated to where the same agent’s cards, email, and KYC live. - Whether the agent may generate media, and how much it may spend doing so, is not something Replicate governs at execution time — it is a token you hold. There is no “may this agent render right now?” check tied to the agent’s broader permission set.
- “Which agent generated this asset, for which end-user, and who let it?” is answered in Replicate’s dashboard for renders, and in unrelated systems for the agent’s spend, comms, and identity.
images and video primitives give the
agent the same capability — submit a generation job, poll it, get a file URL — but it is one set
of primitives on one governed account. And it is honest to say the output is comparable: Naive is
fal.ai-backed and exposes the same FLUX schnell / dev / pro family for images and Kling /
Minimax / Wan for video, so black-forest-labs/flux-schnell on Replicate maps to fal-ai/flux/schnell
on Naive. You keep frontier-model generation and gain:
- The Account Kit that decides whether the agent may
issue a card or send email also decides whether
it may use
images/videoat all — checked at execution time, not in a separate dashboard. - Generation spend is metered in the same credit balance and budget ceiling as every other primitive, so a runaway agent hits one cap, not a separate Replicate bill.
- Every render records the acting agent, lands in the same activity log as its card spend and email sends, and (for video) auto-ingests into the Media Asset Manager alongside the rest of the agent’s assets.
Tested against: the Replicate JavaScript client
replicate v1.4.0 (against the Replicate REST API, base
https://api.replicate.com/v1, POST /v1/predictions + GET /v1/predictions/{id}, docs snapshot
July 2026), and the Naive images / video
primitives over the Naive REST API (base https://api.usenaive.ai/v1, /images/generate,
/video/generate, and the unified /jobs/:id poller, docs snapshot July 2026). The Naive
@usenaive-sdk/server SDK ships dedicated images and video sub-clients —
naive.images.generate() / naive.video.generate() submit the job (shown below); you can also use the
naive images / naive video CLI or raw REST. Poll with
naive.images.status(id) / naive.video.status(id) or the unified naive.jobs sub-client.Version notes:- Auth model differs. Replicate authenticates with an account-wide token (
r8_..., or a defaultnew Replicate()readingREPLICATE_API_TOKEN). Naive authenticates per workspace withNAIVE_API_KEY, and you scope an end-user withnaive.forUser(id)/POST /v1/users/:id/images/generate— the same handle that reaches every other primitive. - Different provider under the hood. Replicate runs models on its own registry/hardware; Naive runs
the fal.ai catalog. FLUX schnell/dev/pro and Kling/Minimax exist on both, so equivalent prompts give
comparable output — but there is no arbitrary-model or
owner/model:versionpass-through, and no BYO Replicate account. See what doesn’t map yet. - Naive is always async. Replicate lets you block on a result with
replicate.run(...)or thePrefer: waitheader (up to ~60s). Naive returns a202 { job_id }you poll on the unified jobs system — no single blocking call. - Completion is polled, not (yet) webhooked per job. Replicate posts a webhook on
start/output/logs/completed. Naive’s generation jobs are polled viaGET /v1/jobs/:id; confirm available inbound events withGET /v1/webhooks/event-typesbefore depending on push.
Concept map
Before / after: the core path
The path that matters for almost every agent is submit a prompt, wait, get an image URL. Here it is on both platforms — same FLUX schnell model on each.- Blocking vs. async. Replicate’s
run(andPrefer: wait) can return the finished output inline. Naive always returns a202 { job_id }; pollGET /v1/jobs/:id(ornaive.jobs.get(id)) untilstatus === "completed". Credits are charged on completion only. - Status vocabulary.
starting/processing/succeeded/failed/canceled→queued/processing/completed/failed/cancelled. - Output shape. Replicate returns a
FileOutput(or array); Naive returnsresult.images[]({ url, width, height, content_type }) with theseedandpromptechoed back. - File lifetime. Replicate removes prediction files after ~1 hour — you re-host them. Naive returns a fal.media URL, and video generations auto-ingest into the Media library.
The async / video path
If you were usingpredictions.create with a webhook (rather than blocking on run), the shape maps
directly to submit-then-poll — shown here for text-to-video:
Minimal viable migration
The smallest swap that keeps a working agent running is submit + poll (images first, video the same way).1
Set your key
Use your existing
NAIVE_API_KEY (a server-side key from the
dashboard). No separate generation vendor account or r8_... token
to provision.2
Pick a mapped model
Swap the Replicate slug for its Naive catalog equivalent:
black-forest-labs/flux-schnell →
fal-ai/flux/schnell, FLUX dev/pro likewise, and video → fal-ai/kling-video/.... List what’s
available with GET /v1/images/models and GET /v1/video/models (or naive images models).3
Swap the submit call
Map
replicate.run(model, { input }) / predictions.create → POST /v1/images/generate
{ model, input: { prompt, ... } }. You get a 202 { job_id } instead of an inline result.4
Swap polling for the jobs system
Replace
replicate.predictions.get(id) with naive.jobs.get(job_id) (or GET /v1/jobs/:id). Loop
while status is queued/processing; read result.images[].url (or result.video.url) on
completed. naive.jobs.cancel(id) replaces predictions.cancel.5
Reach for the CLI where handy
The same primitives are on the CLI:
naive images generate --model fal-ai/flux/schnell "..." --wait,
naive video generate --model fal-ai/kling-video/v3/pro/text-to-video "..." --duration 5 --wait, and
naive jobs get <id>.6
Ship it
At this point the agent’s generation path is off Replicate’s direct API and onto Naive — comparable
FLUX/Kling output, one key. Everything below is upside, not a requirement.
Consolidate further once you’re on Naive
This is where the migration pays for itself. On Replicate, generation is a self-contained account: a token, its own GPU bill, and its own dashboard — disconnected from the agent’s money, comms, and identity. On Naive,images/video are primitives on the same account and Account Kit that governs
the agent’s cards, email, phone, and vault.
Gain #1 — one account across primitives
- With Replicate, generation is an island behind its own token and GPU bill. With Naive,
naive.forUser(acme.id)is a single handle to images and video and cards and email and phone and KYC — no second vendor account, nor8_...token to provision and rotate, no separate invoice. - A content agent’s whole loop lives under one identity: generate a video (
video), find it in the Media library, then post it to social — the same governed user across every step, not three disconnected vendor accounts stitched by hand.
Gain #2 — execution-time permission enforcement
- Whether an agent may generate at all is the
images/videoprimitive on the user’s Account Kit, decided at execution time — not a token you gate separately from everything else the agent can do.
- The agent’s code path stays the same for every tier — the same
POST /v1/video/generate. Whether it runs is decided by policy: a user whose Account Kit does not enablevideois refused withforbidden, with no code change on your side. - Each render spends credits (dynamic, model-dependent, at $0.05/credit — preview with
GET /v1/images/pricing) against the same budget ceiling as the agent’s cards, phone, and LLM calls — so a misbehaving agent trips one combined cap, not a separate Replicate GPU bill you monitor on its own.
images/video are metered and Account-Kit-gated, but — like search and
unlike money-moving primitives (cards, trading, domains) — they are not frozen for human approval by
default. Media generation is company-scoped: the kit gates whether a user’s agent may render.Gain #3 — unified accountability
- Every render records the acting agent and lands in one per-user activity log — alongside that customer’s card spend, email sends, and KYC events, not in a separate Replicate dashboard:
- Generated video (and clips) also auto-ingest into the Media Asset Manager
with
source_type: "video_generation", so the asset library is part of the same governed account — not a pile of expiring Replicate URLs you re-host yourself.
What does not map yet
A migration guide that hides gaps is worse than none. The core path (submit → poll → file URL) maps cleanly for the FLUX/Kling family, but the following Replicate capabilities have no direct equivalent on Naive today. Check this list against your app before you commit.Where to go next
imagesprimitive — fullgeneratereference, models, sizes, pricing, and stock searchvideoprimitive — text-to-video / image-to-video, models, durations- Jobs — the unified poller (
naive.jobs.get/cancel) for image and video generation - Media Asset Manager — where generated video auto-lands, tagged and searchable
- Account Kits — enabling/disabling
images/videoper user at execution time - Billing — the shared credit balance and budget ceiling generation spends against
- Logs — the unified per-user activity trail every render lands in