---
title: "Pixeltable vs LangChain: data plane vs agent runtime"
description: "Pixeltable stores multimodal rows and keeps indexes in sync. LangGraph runs the agent loop. Use Pixeltable for RAG data; keep LangGraph when the graph is the product."
keywords:
  - Pixeltable vs LangChain
  - LangChain alternative
  - LangGraph
  - multimodal RAG
  - LLM framework comparison
  - Python AI backend
  - AI automation workflow
url: "https://pixeltable.com/compare/pixeltable-vs-langchain"
---

# Pixeltable vs LangChain

LangChain and LangGraph run the agent loop. Pixeltable is the data plane: media, computed columns, embedding indexes, and HTTP in one Python file. They are not the same job. Use both, or drop the extra store if Pixeltable already holds the chunks.

## Summary

### Pixeltable

- Tables, computed columns, and embedding indexes in one schema
- Insert a document or image; chunking and indexes update
- Tool-calling via computed columns and invoke_tools
- Same file serves HTTP with FastAPIRouter

### LangChain

- LangGraph for multi-agent graphs, checkpointers, and interrupts
- Huge ecosystem: loaders, tools, callbacks, LangSmith tracing
- The default stack agents already know how to write
- Persistence and retrieval are still someone else’s job

## Comparison

| Feature | Pixeltable | LangChain |
| --- | --- | --- |
| What it is | Multimodal tables + incremental compute + serving | LLM application SDK; LangGraph is the agent runtime |
| Where the bytes live | Native Document, Image, Video, Audio columns | You bring a store: Postgres, Chroma, S3, a checkpointer |
| Chunking and embeddings | document_splitter view + EmbeddingIndex; insert keeps them current | Loaders and splitters you re-run; vectors upserted elsewhere |
| Agent graphs | Tool-calling columns and @pxt.udf tools; no graph runtime | LangGraph: StateGraph, ToolNode, human-in-the-loop, checkpointers |
| Tracing and eval | Per-cell errormsg / errortype; no LangSmith | LangSmith, callbacks, and the tracing ecosystem |
| Multimodal RAG | One schema for PDFs and images; CLIP and text indexes together | Possible; separate loaders, embedders, and stores per modality |
| Team already using it | Python tables; agents learn TableModel from the skill | Default generated stack; LangGraph Platform if you already pay for it |

## RAG that stays in sync

Pixeltable: the schema is chunking, the index, and a tool-calling assistant. LangGraph: you still own the store. Apply Pixeltable with pxt schema update app.py app.

### Pixeltable

```python
import pixeltable as pxt
from pixeltable.functions.document import document_splitter
from pixeltable.functions.huggingface import sentence_transformer, clip
from pixeltable.functions.openai import chat_completions, invoke_tools

TableModel = pxt.model_base()
embed = sentence_transformer.using(
    model_id='sentence-transformers/all-MiniLM-L6-v2'
)
visual = clip.using(model_id='openai/clip-vit-base-patch32')

class Docs(TableModel, name='docs'):
    document: pxt.Document
    image: pxt.Image
    title: pxt.String
    __indexes__ = [pxt.EmbeddingIndex(image, embedding=visual)]

class Chunks(
    TableModel,
    name='chunks',
    base=Docs,
    iterator=document_splitter(
        Docs.document, separators='sentence', limit=512
    ),
):
    __indexes__ = [pxt.EmbeddingIndex(text, embedding=embed)]

@pxt.udf
def search_docs(question: str) -> str:
    chunks = pxt.get_table('app.chunks')
    sim = chunks.text.similarity(string=question)
    rows = (
        chunks.order_by(sim, asc=False)
        .limit(5)
        .select(chunks.text)
        .collect()
    )
    return '\n'.join(r['text'] for r in rows)

tools = pxt.tools(search_docs)

class Assistant(TableModel, name='assistant'):
    message: pxt.String
    response = chat_completions(
        messages=[{'role': 'user', 'content': message}],
        model='gpt-4o-mini',
        tools=tools,
    )
    tool_output = invoke_tools(tools, response)

# pxt schema update app.py app
```

### LangChain

```python
from langchain_community.document_loaders import PyPDFLoader
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_openai import ChatOpenAI, OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain_core.tools import tool
from langgraph.prebuilt import create_react_agent

docs = PyPDFLoader('handbook.pdf').load()
chunks = RecursiveCharacterTextSplitter(
    chunk_size=512, chunk_overlap=50
).split_documents(docs)
store = Chroma.from_documents(
    chunks, OpenAIEmbeddings(model='text-embedding-3-small')
)

@tool
def search_handbook(question: str) -> str:
    hits = store.similarity_search(question, k=5)
    return '\n'.join(d.page_content for d in hits)

agent = create_react_agent(
    ChatOpenAI(model='gpt-4o-mini'), tools=[search_handbook]
)
agent.invoke({'messages': [('user', 'What is the refund policy?')]})
# Images, versioning, and re-chunking on insert are still yours.
```

## When to choose Pixeltable

- **The data layer is the product**: PDFs, images, video, embeddings, and retrieval that must stay current when a row is inserted. One schema, not a loader plus a vector store plus a re-index job.
- **You want retrieval without a second database**: EmbeddingIndex on the column. similarity(string=query) then order_by. LangGraph can call that as a tool.

## When to choose LangChain

- **The agent loop is the product**: Multi-agent graphs, interrupts, checkpointers, and LangSmith traces. Pixeltable does not ship that runtime.
- **The team already writes LangGraph**: Keep the graph. Point tools at Pixeltable tables instead of standing up Chroma for every prototype.

## FAQ

### Is Pixeltable a LangChain alternative?

It replaces the data layer of a LangChain stack (chunking, embeddings, retrieval, persistence). It does not replace LangGraph for multi-agent graphs or LangSmith for tracing. Official map: docs.pixeltable.com/howto/coming-from (LangGraph → TableModel + invoke_tools). Category: agent graph vs table — see pixeltable.com/blog/ai-automation-workflow.

### Can I use Pixeltable with LangGraph?

Yes. Keep the graph. Expose a Pixeltable query or @pxt.udf as a tool so retrieval hits tables instead of a sidecar vector store.

### Does Pixeltable replace LlamaIndex too?

Same job as the LangChain data path: you do not need a second index library if EmbeddingIndex is on the table. LlamaIndex still fits if that is already the query engine contract. Not a separate compare URL.

