All Stories
2026-09-168 min read

Multimodal AI · TableModel · AI Agents · Unified Backend · Declarative Schema · Pixeltable Cloud · Computed Columns

The Unified Multimodal Backend Agents Build With

Pixeltable is the database, orchestration, and serving layers in one Python file. Images, video, audio, and documents live in tables. A transform is a computed column. An index is a declaration, and so is an HTTP route.

Pierre Brunelle

Pierre Brunelle

Pixeltable Team

Summary: Pixeltable is the unified multimodal backend agents build with. Database, orchestration, and serving live in one Python file. Images, video, audio, and documents are column types. A transform is a computed column. An index is a declaration, and so is an HTTP route. Insert a row and everything below it runs. Object storage, a vector database, an orchestrator, and the endpoint code that copies between them collapse into app.py. pip install pixeltable.

Four Products, One File#

The tax was never writing a column. It was the joints before you could write one.

Bytes in an object store. IDs in a warehouse. A DAG that re-runs a world because it cannot see which cells changed. Embeddings in a vector database that nobody invalidates when the source clip dies. A FastAPI file you babysit so the demo has a URL. Each piece is fine. The set is a second job. That is the Frankenstein stack. We spent 2026 deleting it: Never Fuck With Your Backend Anymore.

What remains is a habit. You declare tables, computed columns, indexes, and routes in one file. You apply it. You insert a row. The work runs. You serve the same file. That is the backend a coding agent can keep — not a shopping list of services it has to invent every session.

The File Agents Write#

pxt service example --out app.py writes this. Delete what you do not need. Annotations are stored columns. Assignments are computed columns: they run on insert and on update. A @pxt.udf in the same file is a function those columns can call. Production tables often use uuid7() as a generated primary key; the example uses an integer you insert so the first curl is obvious.

bash
python

title: pxt.String is a value you provide. title_upper = ... is computed. POST /docs inserts and returns the computed columns. POST /titles computes without storing a row. Insert a row. The assignments run. That is the whole orchestration story.

Three Verbs That Are Not Interchangeable#

Agents mix these. The file does not.

pxt schema update creates the catalog my_app and its tables. It does not start HTTP. pxt service update starts HTTP. It does not create tables. On Cloud, pxt db update creates or updates the hosted database — image, workers, disk. It does not insert rows. pxt service run is local only. It cannot target pxt://.

The port is assigned. Read it back rather than hardcoding it:

bash

Media Is a Column#

The same file holds pxt.Image, pxt.Video, pxt.Audio, or pxt.Document. A computed column over one of them is another assignment: frames, transcripts, captions, chunks. That is a multimodal data table, not a FILE path the engine does not understand. Flattening a Gong call into a SQL tag is not beyond SQL. It is also not a system of record for the audio. The post-AI stack still draws a warehouse. Media needs a typed table: The Post-AI Data Stack Needs a Multimodal Table.

An embedding index is a declaration on the class (__indexes__). A query is @pxt.query. HTTP for that query is a route on the same router. You do not stand up a second product to keep the index honest. Insert is the pipeline.

Same File on Cloud#

Create an API key in the Cloud dashboard, set PIXELTABLE_API_KEY, name the database in pixeltable.toml, then target it by URI. A @pxt.udf in that same app.py is in the image pxt db update builds. Promotion is the file you already ran, not a rewrite into a warehouse dialect. That is why the local-cloud loop is the lifecycle, not a staging cluster.

bash

Order matters. Schema first against a hosted database that does not exist yet is a 404 on the UDF. Database, then schema, then service.

What Agents Copy vs Invent#

Hand the agent get-started.md. That playbook installs the package, the Pixeltable Skill, and MCP. The capability file is skill.md. How you design for that customer — install via npx, evaluate via a machine-readable overview, buy by writing app.py — is Designing Software for LLMs as Customers.

bash

The skill writes a TableModel in app.py. If the agent writes create_table in application code, names the file schema.py, or writes the removed command pxt serve, the installed skill is stale. Reinstall it. Notebooks and tests still use pxt.create_table(). An app puts tables in app.py and creates them with pxt schema update. Do not mix both styles for the same tables.

pxt service example is the generic file. uvx pixeltable-new copies one app from the starter kit — the acquisition artifact we learned to ship so agents do not default to LangChain plus a vector DB: What We Learned Shipping Application Templates for AI Agents. The default copy is a chat app; pass agent as the last argument to pxt schema update. --video copies video search; pass videointel.

bash

Inserting into the knowledge table needs no API key. The /ask route needs ANTHROPIC_API_KEY.

To mount the routes on an existing FastAPI app, app.include_router(...). To skip endpoints, run pxt schema update, insert from Python, then export_sql if you need a warehouse bridge. Self-hosting is the same schema without the hosted target.

What This Is Not#

It is not no-code. If you do not want a schema, Pixeltable is the wrong product. The point is that the schema is the backend. The persona version of shrinking that surface — Lovable for people who do not write backends, Pixeltable for people who do — is Making Multimodal More Lovable.

It is not “don’t use FastAPI.” FastAPIRouter is FastAPI derived from the catalog. You do not write the handlers. You still get HTTP.

It is not a warehouse replacement. Keep Snowflake or Databricks for Card TPV and NRR. Do not start the video graph in a generic FILE column.

And it is not “use our agent.” Use yours. Pixeltable is the catalog your agent writes to. MCP and HTTP are adapters on that catalog, not a second semantic language.

People Also Ask#

Is TableModel required? For new apps, yes — it is the public schema. The notebook form (create_table, add_computed_column) still exists for one-off scripts. Do not mix both styles for the same tables.

Do I still need Pinecone, Airflow, and an object store? Not as a default architecture. Media, computed transforms, embedding indexes, and HTTP live in one system. You can still point media at your bucket. You should not need a sync job to keep three products from drifting.

How do I go to Cloud? Same app.py. Set PIXELTABLE_API_KEY, declare pxt://org:db, then pxt db updatepxt schema updatepxt service update. Hosted HTTP is on the website dashboard. pxt service run is local only.

Can I mount this on an existing FastAPI app? Yes. app.include_router(...) the routers this file declares. To skip HTTP entirely, apply the schema and insert from Python.

The agent wrote create_table / pxt serve / schema.py. The skill is stale. Reinstall npx skills add pixeltable/pixeltable-skill and hand it get-started.md.

Keep the File, Delete the Stack#

The backend is one schema you keep, not a stack you assemble. Agents can keep a file. They cannot keep a Frankenstein.

Declare the class. Apply it. Insert a row. Serve the same file.

Declarative. Multimodal. Incremental.

Focus on innovation, not infrastructure.

10-minute tutorial · Join community