This documentation page is also available as an interactive notebook. You can launch the notebook in
Kaggle or Colab, or download it for use with an IDE or local Jupyter installation, by clicking one of the
above links.
Convert a table with computed columns into a callable function for
multi-agent workflows and pipeline composition.
Problem
You have a table that runs a complex pipeline—LLM calls, tool use,
post-processing—and you want to reuse that entire pipeline from other
tables. Copy-pasting computed column definitions is error-prone and hard
to maintain.
Solution
What’s in this recipe:
- Create an “agent” table with computed columns
- Convert the table to a callable UDF with
pxt.udf(table, return_value=...)
- Use the table UDF in other tables’ computed columns
You wrap an entire table pipeline as a function. When you call this
function from another table, it inserts a row into the agent table, runs
all computed columns, and returns the specified output column.
Setup
%pip install -qU pixeltable openai
import os
import getpass
if 'OPENAI_API_KEY' not in os.environ:
os.environ['OPENAI_API_KEY'] = getpass.getpass('OpenAI API Key: ')
import pixeltable as pxt
from pixeltable.functions.openai import chat_completions
# Create a fresh directory
pxt.drop_dir('table_udf_demo', force=True)
pxt.create_dir('table_udf_demo')
Connected to Pixeltable database at: postgresql+psycopg://postgres:@/pixeltable?host=/Users/pjlb/.pixeltable/pgdata
Created directory ‘table_udf_demo’.
<pixeltable.catalog.dir.Dir at 0x17fd6e9d0>
Create an agent table with computed columns
You create a table that encapsulates a complete pipeline. This example
builds a summarization agent:
# Create the agent table with input column
summarizer = pxt.create_table(
'table_udf_demo.summarizer',
{'text': pxt.String}
)
Created table ‘summarizer’.
# Add the LLM call as a computed column
summarizer.add_computed_column(
response=chat_completions(
messages=[{
'role': 'user',
'content': 'Summarize this in one sentence:\n\n' + summarizer.text
}],
model='gpt-4o-mini'
)
)
Added 0 column values with 0 errors.
No rows affected.
# Extract the summary text
summarizer.add_computed_column(
summary=summarizer.response.choices[0].message.content
)
Added 0 column values with 0 errors.
No rows affected.
Convert the table to a UDF
You use pxt.udf(table, return_value=...) to convert the table into a
callable function. The return_value specifies which column to return:
# Convert the summarizer table into a callable UDF
summarize = pxt.udf(
summarizer,
return_value=summarizer.summary
)
Use the table UDF in another table
You can now use summarize() as a computed column in any other table:
# Create a table that uses the summarizer
articles = pxt.create_table(
'table_udf_demo.articles',
{'title': pxt.String, 'content': pxt.String}
)
Created table ‘articles’.
# Add the table UDF as a computed column
articles.add_computed_column(
summary=summarize(text=articles.content)
)
Added 0 column values with 0 errors.
No rows affected.
# Insert articles - summaries are generated automatically
articles.insert([
{
'title': 'Climate Report',
'content': 'Global temperatures rose by 1.2 degrees Celsius above pre-industrial levels last year, marking the hottest year on record. Scientists attribute this to continued greenhouse gas emissions and a strong El Nino pattern. The report calls for immediate action to reduce carbon emissions.'
},
{
'title': 'Tech Merger',
'content': 'Two major semiconductor companies announced a merger valued at $50 billion. The combined entity will control 30% of the global chip market. Regulators in multiple countries will review the deal over the next 18 months.'
},
])
Inserting rows into `articles`: 2 rows [00:00, 196.58 rows/s]
Inserted 2 rows with 0 errors.
2 rows inserted, 6 values computed.
# View results
articles.select(articles.title, articles.summary).collect()
Explanation
How table UDFs work:
Consumer table row → Table UDF called → Agent table inserts row →
Computed columns run → Return value extracted → Consumer gets result
When to use table UDFs vs @pxt.query:
Key benefits:
- Encapsulation: Hide complex pipeline details behind a simple
function call
- Reusability: Use the same agent from multiple consumer tables
- Persistence: All intermediate results are stored in the agent
table for debugging
- Composition: Chain agents together for multi-stage workflows
See also