Agent Engineering with Pydantic + Graphs——对话 Pydantic Logfire CEO Samuel Colvin
Pydantic 的 AI 杠杆来自它掌握了 Python 的类型化数据边界,而不是因为它最初就是为 LLM 设计的。 Colvin 提到,Pydantic 仅 12 月就有近 3 亿次下载;他还表示,一家未具名的基础模型公司从 Pydantic v1 迁移到 v2 后,将首 token 延迟缩短了 20%。“AI 算是找上了我们”,但这种意外形成的定位,如今让 Pydantic 在模型 SDK 和结构化输出工具中获得了不同寻常的分发能力。
Pydantic AI 押注于生产工程能力,认为这将区分经得起时间考验的 agent 框架与机会主义封装层。 Colvin 批评整个生态在类型检查、覆盖率、lint 和文档纪律上都很薄弱,同时承认 LangChain 等早期项目当时是在创造一个新类别。Pydantic AI 接受更复杂的泛型设计,以换取生产安全:每个文档示例和打印结果都在测试中运行,因为这些实践本应是“无需思考的基本功”。
类型安全的图谱让 Colvin 改变了对编排的看法:原本蔓延的控制流被转化为可检查的 Python。 节点返回下一个有类型约束的节点,Pydantic 因此可以推断合法边,并在无需字符串式图定义的情况下生成 Mermaid 图。如今,标准 agent 实现本身就是一张图,但持久化状态存储和分布式执行仍在规划中,尚未完成。
Agent 框架正在弥补模型能力的不足,因此随着模型变强,其长期价值可能下降。 Alessio 提出“苦涩的教训”:开发者可以手工搭建反思和路由图,但更大、训练更充分的模型最终可能直接吸收这套工作流。Colvin 表示认同,并将今天受约束的 agent 比作训练不足的呼叫中心员工——他们需要脚本;“它们越聪明,我们就越不需要告诉它们该做什么。”
Logfire 的核心判断是,AI 可观测性不能继续与应用可观测性割裂。 Colvin 认为,包含模型 prompt 的 trace 所携带的敏感信息将比传统遥测“高出一个数量级”,因此部分客户会重视自托管。Logfire 因而定位于通用可观测性,同时提供一等 AI 支持;OpenTelemetry 的语义约定则可能统一不同框架中的模型调用数据。
Logfire 底层的基础设施押注在技术上有差异化,但商业代价高昂。 团队先后从 ClickHouse 转向 Timescale,最终选择 DataFusion,优先考虑 Rust 的可扩展性、对用户友好的 SQL 和开源架构,而不是更快上市。Colvin 承认这一选择“肯定拖慢了我们”,但它避免把利润让给托管数据库供应商,也让 Pydantic 可以自行实现缺失的计算内核。
管理层在保护 runway 的同时,利用开源和浏览器 demo 提升转化。 Pydantic 和 Pydantic AI 仍采用 MIT 许可证,而 Logfire 明确是闭源、营利性产品;尽管团队实际上同时在运营“3 到 4 家初创公司”,Colvin 仍希望在招聘前先获得更多收入。浏览器版 pydantic.run 旨在让潜在客户直接运行经过测试的示例,消除环境配置摩擦;团队计划加入模型代理,并可能与 Logfire 集成。
1. Pydantic 几乎是偶然成为 AI 基础设施的
Colvin 说,把 Pydantic 称为验证库只是近似说法:它利用 Python 类型提示定义 schema、验证输入,并默认执行合理的类型转换。要求一个整数但收到
"123"时,结果会变成123;严格模式则会关闭这一行为。Colvin 于 2017 年开始做这件事时,用类型提示实现上述功能“确实不被一些人认可”。Pydantic 的普及,以及建立在其之上的 FastAPI 的成功,帮助这种模式在 Python 生态中成为惯例。
JSON Schema 并不是结构化输出委员会经过系统决策后选定的。Sebastian Ramírez 在 Pydantic v1 之前加入,大约利用 50 个周末提交或通知,为 FastAPI 和 OpenAPI 增加 JSON Schema 支持;这后来让一份 Pydantic 定义可以同时作为验证、序列化、工具和 LLM 结构化输出的事实来源。
基于 Rust 的 v2 重写带来的回报,不只体现在 benchmark 上:据称,一家未具名的大型基础模型公司从 Pydantic v1 升级到 v2 后,将内部最重要的延迟指标——首 token 延迟——降低了 20%。
2. Pydantic v3 应在不再经历创伤性重写的情况下叠加性能
Colvin 说,“某个时候肯定会有 v3”,但它造成的代码破坏应远小于 v2;后者将大规模 Rust 重写,与修复从 v0 时代遗留下来的问题结合在了一起。
一个拟议中的变化,是在真正需要 Python 对象之前,持续用 Rust 原生表示保存已验证数据。这样一来,验证紧接着序列化时就可以完全跳过一次 Python 转换,理论上还能带来“再快 3 到 5 倍”的提升。
进一步的工作包括更容易地为 NumPy 数组等类型提供自定义处理、让 SIMD JSON 解析覆盖 amd64 之外的架构,以及可能采用 CBOR 之类的二进制格式来存储和重新加载 Pydantic 数据。
Colvin 于 2022 年初全职开始 Rust 重写,持续了 1 年半。他说,这类工作很少有初创公司会批准:3名工程师全职投入 1 年,为一个免费库编写约 30,000 行 Rust。但这也让公司继续处于 Python AI 技术栈的核心位置。
3. 生产纪律是 Pydantic AI 的切入口
在此前 1 年半的大部分时间里,Pydantic 都在打造通用 Logfire 可观测性,而不是追逐 AI。需求将它拉了回来:Colvin 估计,全球新建的 Python 项目中可能约 80%涉及生成式 AI——“显然在加州是 100%”——这意味着仍有大量工具需求没有解决。
他对 agent 框架的批评尖锐但有所保留。LangChain 早期在探索这个类别时,跳过成熟工程实践是可以理解的;但一些受尊敬的名字最近推出的版本更像是“机会主义”,工程质量“远低于 Python 生态其他部分”。
Pydantic AI 将类型检查、覆盖率、lint 和可执行文档置于优先位置。对于理解 Rust 风格类型系统的开发者来说,它的泛型可能更容易接受;但 Colvin 认为,在大型生产应用中,静态检查的收益足以抵消复杂性,因为这本来就是“无需思考的基本功”。
它的基础 agent 包含系统 prompt、工具、可选的结构化结果、依赖项、模型和设置。Colvin 称这些对象更接近“agentlet”:开发者通常会把多个 agentlet 组合起来,才形成用户所理解的完整 agent。
配套的
pytest-examples工具会从 docstring 和 Markdown 中提取 Python 代码,运行并 lint,近期还将加入类型检查。这正是团队保持数百个可运行、自包含示例持续更新的方式。
4. 有类型的返回值让图谱可检查,而不是依赖字符串
Colvin 最初认为,普通 Python 控制流足以表达任何 agent 工作流。反复遇到的案例动摇了这一立场:他维护过由此产生的“意大利面代码”,也看到了结构化表示能够自我解释的价值。
Pydantic 的图节点通常是 dataclass,其运行方法返回下一个允许的节点。检查这些返回类型和联合类型,就能揭示合法边,避免使用未经检查的字符串命名连接、再靠运行时验证兜底的图 API。
回报同时体现在安全性和可读性上:仅凭类型提示,就能生成一张 Mermaid 图,准确展示可能发生的路径。Colvin 说,“把这一点做对之后”,他对图谱“异常兴奋”。
Pydantic AI 的常规 agent 实现已经合并到图引擎上,公共 API 没有变化。底层执行仍刻意保持简单:调用一个节点,得到另一个节点,重复这一过程,直到出现
End值。
5. 持久化工作流暴露出图谱库仍缺少的能力
Colvin 最好的例子是电商退货流程:图中将两条性质完全不同的边视为相同,一条代表立即调用函数,另一条则意味着等待 6 天,让客户打印标签并寄出包裹。概念验证可以对这个暂停一笔带过,但生产环境不行。
图谱可以通过实例化适当节点,并将其作为新的起点来恢复执行。Pydantic AI 已经在问答流程中使用这一模式,但在每个节点之间通过数据库持久化状态,仍是团队计划“很快”加入的能力。
swyx 受 Temporal 启发提出反驳:Python 库本身并不提供隔离执行或基础设施韧性。Colvin 同意,最终每个单元都应在自己的容器或 worker 中运行;只要每个 worker 的代码兼容,将下一个节点的调用序列化后就可以分布式执行。
他偏好的实验载体是通过 Pyodide 运行 Python 的 Cloudflare Workers,因为这样可以无服务器地启动数千个隔离函数。二进制依赖共享仍然困难,但 pydantic-core 这类 Rust 库可以编译为 WebAssembly。
6. Pydantic 在验证编排需求,但没有宣称要建立帝国
主持人将演进路径概括为:从单 agent,到委派和程序化交接,再到基于图的控制流。Colvin 回忆,OpenAI 曾告诉他,Pydantic AI 看起来像是 Swarm“如果做到生产可用后”会变成的样子;他补充说,“也许我不该说这个。”
为了复现 Swarm 直观的使用感,他开始转向图谱,因为“直接用 Python 代码调用下一个 agent”无法满足用户。但仅仅过了几周,他还没有形成标准的前五大图谱分类;他想先看看开发者实际会构建什么。
Colvin 拒绝宣布已经战胜 LangChain:“那是你们该去查清楚的事,不是我的。”Pydantic 目前仍是一个库,而不是 Temporal、Prefect、Airflow 或 Dagster 所提供的部署基础设施;他说,最小图谱抽象究竟有多大用处,仍需通过实践验证。
他对控制力最强的论据来自经济层面:大型自主运行可能在错误变得可见前就消耗大量时间和资金。逐节点迭代能让应用检查进度并及时退出,而不是等模型已经漫游很久后,才被一个笼统的最大步数错误打断。
7. 更好的模型可能抹去今天大量的 agent 脚手架
Alessio 提出“苦涩的教训”式质疑:开发者拆解任务、加入反思,并编排推理时算力;而研究人员可能训练一个更大的模型直接吸收这套模式,比如把 Strawberry 变成 DeepSeek R1。“我们正在这里与苦涩的教训对抗。”
Colvin 基本认同。如果模型真能像支持者暗示的那样,快速变得更快、更强,应用可能只需给一个模型互联网访问权限,“双手合十,祈求一切顺利”,从而不再需要 agent、框架和图谱中的很大一部分。
他的类比来自客服行业:银行会为训练不足的呼叫中心员工编写严密脚本,而面向高净值客户的银行则会雇用那些被期待能在咖啡桌前打动客户、并拥有自主判断权的人。“它们越聪明,我们就越不需要告诉它们该做什么”,也越不需要限制它们的路径。
在此之前,复合系统仍会创造有用的干预点。Agent“在运行良好时确实运行良好”,但仅有可观测性并不能阻止一次糟糕的运行;显式节点则为开发者提供了检查、重定向或终止的位置。
8. 模型可移植性与 eval 仍是悬而未决的工程问题
swyx 质疑每个框架都维护 OpenAI、Claude、Google 等模型的适配器,倾向于采用 LiteLLM 或 Portkey 这样的共享层。当他以 DeepSeek 为缺失案例时,Colvin 立即纠正说:Pydantic AI 已经支持它。
Colvin 的顾虑包括类型安全、关于适配器质量的未经确认的报告,以及标准化代理可能将请求转发给另一家公司的风险。他还看到行业正围绕 OpenAI API 收敛:DeepSeek、Grok 和 Ollama 都在实现它,使 OpenAI SDK 成为事实上的兼容层。
Pydantic AI 会在提交合并到 main 时运行一小组真实模型测试。据称,Google 的 Generative Language API 当时约有 20%的请求返回 503 错误,并反复导致测试失败;而 Vertex 暴露了类似 API,但可靠性明显更高。
Pydantic AI 还支持 test-model 和 function-model 方案,可以在不发起真实调用的情况下模拟模型行为。至于 eval,Colvin 的“诚实答案”是,他不知道普适解。30 个示例可能以 15%的工作量提供 200 个示例大部分的统计价值,但选择正确的评估设计更难;因此 Logfire 暴露 SQL,让用户探索自己的生产数据,而不是接受一套预设框架。
9. Logfire 将 AI trace 与应用其他部分连接起来
Colvin 预计,“AI 可观测性”最终会像 Web 可观测性和云可观测性一样消失为一个独立类别:所有通用平台最终都需要它。他的切入口是通用可观测性加一等 AI 支持,因为只看模型的 trace 会遗漏太多周边应用行为。他也看到了开发者体验上的机会:Sentry 让 Python 接入很容易,而基础的 Datadog/Python 配置并不简单。
OpenTelemetry 正在向生成式 AI 语义属性收敛,最初主要围绕单次 LLM 调用。Agent 层面的约定仍不成熟,消息也在转向 OTel events;Colvin 指出,prompt 和 completion token 字段可能会把昨天的范式固化下来,因为推理 token 和采样方法都在变化。
更深层的问题是数据敏感性。传统遥测会尽量省略参数:医院的 SQL trace 不需要暴露患者身份或 STI 药物。但在生成式 AI 中,这些事实纠缠在自然语言 prompt 里,因此普通的密码键名清洗无法可靠奏效,部分客户也会要求自托管。
Logfire 还会在 span 开始时输出信息,而不是只在结束时输出。等待一个 20 秒的模型请求——或一个 30 分钟的批处理任务——结束后才显示 trace,是“致命的”;提前获得 span 数据,可以让运营人员观察长时间运行的工作如何展开。
Colvin 说,LangChain 有自己的可观测性平台,没有走 OpenTelemetry 路线,因此外部埋点更加困难。Pydantic 的优势在于它控制自己的 agent 框架,可以直接实现这些约定。
10. DataFusion 与克制增长定义了这场商业押注
Logfire 先从 ClickHouse 转向 Timescale,随后又转向 DataFusion;Colvin 承认,这段历程并没有让董事会成员高兴。当时 ClickHouse 的 JSON 支持不够便利,在 interval 和 datetime 上也有令人痛苦的边界问题,尤其是在用户必须自行编写大量时长相关 SQL 的情况下。
DataFusion 是“用来构建数据库的工具箱,而不是数据库”。它基于 Rust 的实现让 Pydantic 可以优化字符串比较内核,并用自己的解析器加入 JSON 支持;Colvin 说,后者是他用一个周末实现的。
这一选择也保住了经济性:ClickHouse 和 Timescale 主要通过托管产品提供对象存储加缓存的架构,而这些托管产品的利润会成为 Logfire 自身利润之下的一层。Colvin 承认,相比在 ClickHouse 上快速发布,DataFusion“肯定拖慢了我们”,但他希望长期来看,开放架构能够胜出。
Pydantic 和 Pydantic AI 采用 MIT 许可证;Logfire 则明确是闭源、营利性产品。开源浏览器沙盒 pydantic.run 旨在运行经过测试的示例,消除本地配置摩擦;Colvin 计划加入 OpenAI 和其他模型的代理,也可能把它接入 Logfire。他希望在招聘前先获得更多商业牵引:“有几年的 runway,而不是几个月,感觉相当不错。”
This is Alessio Fanelli, partner and CTO at Decibel Partners, and I'm joined by my co-host, swyx, founder of Smol AI.
Good morning.
Today, we're very excited to have Sam Colvin join us from Pydantic AI. Welcome.
Thank you so much for having me. It's great to be here.
Sam, I heard that Pydantic is all we need. Is that true?
I would say you might need Pydantic AI and Logfire as well, but it gets you a long way, that's for sure.
Pydantic almost needs no introduction. It's almost 300 million downloads in December, and obviously, in the previous podcasts and discussions we've had with Jason Liu, he's been a big fan and promoter of Pydantic.
It's weird because I didn't create Pydantic originally for uses in AI. It obviously predates LLMs, but we've been lucky that it's been picked up by that community and used so widely. Maybe we'll hear it right from you: what is Pydantic, and maybe a little bit of the origin story?
The best name for it, which is not quite right, is a validation library. We get some tension around that name because it doesn't just do validation; it will do coercion by default. We now have strict mode, so you can disable that coercion.
By default, if you say you want an integer field and you get a string of 123, it will convert it to 123, along with a bunch of other sensible conversions. As you can imagine, the semantics around exactly when you convert and when you don't are complicated. But because of that, it's more than just validation.
Back in 2017, when I first started it, the different thing it was doing was using type hints to define your schema. That was controversial at the time. It was genuinely disapproved of by some people. I think the success of Pydantic and libraries like FastAPI that build on top of it means that today, that's no longer controversial in Python. Indeed, lots of other people have copied that approach.
It's a data-validation library that uses type hints for the most part and does all the other things you want, like serialization, on top of that. But that's the core.
Do you have any fun stories about how JSON Schema ended up being the structured-output standard for LLMs? Were you involved in any of those discussions? I know OpenAI was one of the early adopters. Did they reach out to you? Was there some kind of structured-output council in open source that people were talking about, or was it just random?
Very much not so. I originally didn't implement JSON Schema inside Pydantic, and then Sebastian Ramirez's FastAPI came along. The first I ever heard of him was over a weekend, when I got 50 emails from him—or 50 emails as he was committing to Pydantic—adding JSON Schema, long before version 1.
The reason it was added was for OpenAPI, which is obviously closely linked to JSON Schema. I don't know why JSON Schema got picked up and used by OpenAI. It was obviously convenient for us because, as I mentioned, not only can you do the validation, but because Pydantic will generate the JSON Schema, it can be one source of truth for structured outputs and tools.
Before we dive further into the AI side of things, something I'm mildly curious about: obviously, there's Zod in JavaScript land. Every now and then there's a new validation library that's in vogue and takes over for a few years, and then something else comes along. Is Pydantic done?
I've just come off a call where we were redesigning some of the internal bits. There will be a version 3 at some point, which will not break people's code half as much as version 2. Version 2 was the massive rewrite in Rust, but it also fixed all the things that had been broken since version 0 that we didn't fix in version 1 because it was a side project.
We have plans to move some of the data storage into Rust types after validation, rather than converting to Python types. If you were doing validation and then serialization, you would never have to go via a Python type. We reckon that could give us another 3–5x speedup. That's probably the biggest thing, along with changing how easy it is to extend Pydantic and define how particular types—for example, NumPy arrays—are validated and serialized.
There's also work going on in Jiter, the JSON library that does JSON parsing in Rust. It has a SIMD implementation at the moment only for amd64, so we need to add SIMD for other instruction sets. There's a bunch more we can do on performance.
I don't think we're going to revolutionize Pydantic, but it's going to continue to get faster and, hopefully, allow people to do more advanced things. We might add a binary format like CBOR for serialization, for when you just want to put the data into a database and probably load it again from Pydantic. There are some things that will come along, but for the most part it should just get faster and cleaner.
From a focus perspective, I guess, as a founder too, how did you think about the AI interest rising? How did you prioritize what was worth going into more deeply? What was your early experience with LLMs, and when did you figure out that this was something you should take seriously and focus more resources on?
I think the parallel question is that Pydantic is weird because it existed before I was starting a company. I was working on it in my spare time, and then at the beginning of 2022 I started working on the rewrite in Rust. I worked on that full-time for a year and a half, and then, once we started the company, people came and joined.
It was a weird project because that would never get signed off inside a startup: “We're going to have 3 engineers work full-time for a year in Python and Rust, writing 30,000 lines of Rust just to release a free, open-source Python library.” The result of that has been excellent for us as a company. It's made us remain entirely relevant. Pydantic is not just used in the SDKs of all the AI libraries.
I can't say which one, but one of the big foundational-model companies upgraded from Pydantic v1 to v2, and their number-one internal performance metric was time to first token. That went down by 20%. You think about all the actual AI going on inside, and yet at least 20% of the CPU usage—or at least the latency—inside requests was actually Pydantic. That shows how widely it's used.
In answer to your question about how we prioritize AI, the honest truth is that we've spent a lot of the last year and a half building good general-purpose observability inside Logfire and making Pydantic good for general-purpose use cases. AI has kind of come to us.
The appetite, both in Pydantic and in Logfire, to build with AI is enormous because it makes sense. If you're starting a new greenfield project in Python today, what's the chance that you're using GenAI? Globally, let's say 80%. Obviously, it's 100% in California, but even worldwide it's probably 80%.
Everyone needs this stuff, and there's so much yet to be figured out—so much space to do things better in the ecosystem. Going and implementing a database that's better than Postgres is a Sisyphean task, whereas building tools that are better for GenAI than some of what's available now is not very difficult, putting the actual models themselves to one side.
You released Pydantic AI recently, which is an agent framework. Early on, I would say everybody—LangChain, Instructor, and a lot of these frameworks—were trying to use Pydantic to be better. What was the decision behind doing your own framework? Were there design decisions you disagreed with, or workloads that you thought people weren't supporting well?
It wasn't so much about design or workflow, although I think there are some things we've done differently. Looking in general at the ecosystem of agent frameworks, the engineering quality is far below that of the rest of the Python ecosystem.
There's a bunch of stuff that we've learned how to do over the last 20 years of building Python libraries and writing Python code that seems to be abandoned when people build agent frameworks now. I can respect that, particularly in the very first agent frameworks like LangChain, where people were literally figuring out how to do this stuff. It's completely understandable that you would skip some standard best practices to get something built.
I'm shocked by the quality of some of the agent frameworks that have come out recently from well-respected names. It seems to be opportunism, and I have little time for that. The early ones, though, were just figuring out how to do things, and just as lots of people have learned from Pydantic, we were able to learn a bit from them.
The gap we saw, and the thing we were frustrated by, was production readiness. That means things like type checking. Even when type checking makes things hard, Pydantic AI has a lot of generics. You probably find it easier to use if you've written a bit of Rust and really understand generics. We don't claim that makes it the easiest thing to use in all cases, but we think it makes it good for production applications in big systems where type checking is a no-brainer in Python.
There are also a bunch of things we've learned from maintaining Pydantic over the years. Every single example in the Pydantic AI documentation is run as part of the tests, and every single print output within an example is checked during testing. It will always be up to date.
Then there are things that are standard best practices within the rest of the Python ecosystem but aren't followed surprisingly often by some AI libraries: coverage, linting, type checking, and so on. I think these are no-brainers, but weirdly, they're not followed by some of the other libraries.
Can you give us an overview of the framework itself? There are the LLM-calling frameworks, the multi-agent frameworks, and the workflow frameworks. What does Pydantic AI do?
I glaze over a bit when I hear all of the different sorts of frameworks. When I built Pydantic, Logfire, and Pydantic AI, my methodology was not to research and review all of the other things. I work out what I want and go build it. Then feedback comes, and we adjust.
The fundamental building block of Pydantic AI is agents. The exact definition of agents and how you want to define them is obviously ambiguous. They are probably sort of agentlets, although we wouldn't want to rename them that. The point is that you probably build them together to build something that most people would call an agent.
In our case, an agent has things like a system prompt, some tools, and a structured return type if you want that. That covers the vast majority of cases.
There are situations where you want to go further, with the most complex workflows where you want graphs. I resisted graphs for quite a long time. I was of the opinion that you didn't need them and could use standard Python flow control to do all of that stuff. I had a few arguments with people, but I basically came around to seeing that graphs are useful.
The problem is that, by default, they're not type-safe. If you have an `add_edge` method where you give the names of different edges, there's no type checking. Even if you do some of that, not all graph libraries are AI-specific. There's a graph library called Burr that does runtime type checking—ironically using Pydantic—to try to make up for the fact that, fundamentally, its graphs aren't type-safe.
I like Pydantic, but it's not a real solution to have to run the code to see if it's safe. There's a reason static type checking is so powerful. Eventually, we came up with a system of using, normally, data classes to define nodes, where you return the next node you want to call. We're able to introspect the return type of a node to build the graph, so the graph is inherently type-safe.
Once we got that right, I was—and am—incredibly excited about graphs. I think there are masses of use cases for them, both in GenAI and other development. Software is all going to have to interact with GenAI. There won't be a web department in a company anymore; all the developers will be building for the web, building with databases, and doing the same thing with GenAI.
I see on your docs that you call an agent a container that contains a system prompt function, tool, structured result, dependency type, model, and model settings. Are the graphs, in your mind, different agents? Are they different prompts for the same agent? What are the structures in your mind?
We were compelled enough by graphs, once we got them right, that we merged a PR this morning. Our implementation, without changing its API at all, is now actually a graph under the hood. It's built using our graph library.
Graphs are basically a lower-level tool that allows you to build these complex workflows. Our agents are technically one of the many graphs you could build. We just happen to build that one for you because it's a very common one. There are cases where you need more complex workflows where the current agent assumptions don't work, and that's where you can use graphs to build more complex things.
You said you were cynical about graphs. What changed your mind specifically?
People kept giving me examples of things they wanted to use graphs for, and my argument that you could do that with standard Python flow control became less and less compelling. I've maintained systems that end up with spaghetti code, and I could see the appeal of this structured way of defining the workflow of my code.
It's also really neat that, just from your code and your type hints, you can get a Mermaid diagram that defines exactly what can happen.
You do have a very neat implementation of inferring the graph from type hints. Is that what you would call it?
Exactly. If you look at the internal logic of actually running a graph, it's incredibly simple. It's basically: call a node, get a node back, call that node, get a node back, call that node. If you get an end, you're done.
We'll add support soon for storage, so you can store the state between each node that's run. Then you could distribute a graph and run it across compute.
The other bit that's really valuable is across time. It's all very well when Claude gives you an example with a lovely, enormous Mermaid chart for a workflow, say, managing returns for an e-commerce company. But some of those lines are literally one function calling another, while others mean, “Wait 6 days for the customer to print their piece of paper and put it in the post.”
If you're writing a demo project or proof of concept, that's fine because you can just say, “And now we call this function.” But in real life, that doesn't work. How do we manage the concept of being able to start somewhere else in our code?
This graph implementation makes it incredibly easy. You just pass the node that's the starting point for carrying on the graph, and it continues to run. It's things like that where I can imagine how systems I've built in the past would have been fundamentally easier to understand if we'd done them with graphs.
When you say “imagine,” does Pydantic AI actually resume 6 days later, like you said, or is that a theoretical thing we can do someday?
I think it's basically a Q&A pattern. There's an AI asking the user a question, and you then call the graph again to continue the conversation. It instantiates the node and calls the graph with that node again.
We don't yet have the logic for storing state in the database between individual nodes. We're going to add that soon, but the rest of it is basically there.
It does make me think that you're not only competing with LangChain and, obviously, Instructor; now you're going into the more orchestration-oriented tools like Airflow, Prefect, and Dagster.
We're good friends with the Prefect guys, and Temporal has the same investors as us. I'm sure my investor Bill would not be too happy if I said, “By the way, as well as trying to take on Datadog, we're also going to take on Temporal and everyone else doing that.”
Obviously, we're not doing all of the infrastructure for deploying that yet, at least. We're just building a Python library. What's crazy about our graph implementation is that, sure, there's a bit of magic in introspecting the return type and extracting things from unions, but the actual calls are literally just calling a function, getting something back, and calling the next function. It's incredibly simple and therefore easy to maintain.
The question is how useful it is. I don't know yet. We have to find out. We've had a slew of people joining our Slack over the last few days asking how good Pydantic AI is versus LangChain. I refuse to answer. That's your job—to go find that out. We've built a thing that I'm compelled by, but I'm obviously biased. The ecosystem will work out what the useful tools are.
Bill was my board member when I was at Temporal. I think that, generally, having been a workflow-engine investor and participant in this space, it's a big space. Everyone needs different flavors of orchestration.
The one thing I would say is that, as a library, you don't have that much control over the infrastructure. I do like the idea that each new agent—or whatever unit of work you call it—should spin up in isolated boundaries. Ideally, you want to spin out its own little container. With Pydantic AI, I think everything runs in the same process.
I agree with you 100%. It would work now, in theory. As long as you can serialize the calls to the next node, all of the different containers just have to have the same code.
I'm super excited about Cloudflare Workers running Python and being able to install dependencies. If Cloudflare would give me my invitation to the private beta, we'd be exploring that right now. I'm really excited about that as a compute layer for some of this stuff.
You can run everything as an individual worker function and distribute it, and it's resilient to failure. It spins up like a thousand businesses simultaneously. You want it to be truly serverless.
I know we have some Cloudflare friends listening, so hopefully they'll get you to the front of the line.
I was in Cloudflare's office last week, shouting at them about other things that frustrate me. I have a love-hate relationship with Cloudflare. Their technology is awesome, but because I use it all the time, I get frustrated. I'm sure I'll get there soon.
Is the Python support full? I wasn't fully aware of the status of that.
Pyodide, which is Python running inside the browser through WebAssembly, is supported by Cloudflare now. They're having some struggles working out how to manage dependencies that have binaries, particularly Pydantic.
Because these Workers can have thousands of instances on a given metal machine, you don't want a different copy of Pydantic in each one. You want shared memory for all the different Pydantic installations. That's the thing they're working out.
Hood Chatham, who's a friend of mine and one of the primary maintainers of Pyodide, works for Cloudflare, and that's basically what he's doing: working out how to get Python running on Cloudflare's network.
The nice thing is that your binary is written in Rust, which also compiles to WebAssembly. Maybe there's a way to build a different version of Pydantic that ships with whatever driver Cloudflare Workers need.
So you already have a different build of Pydantic that compiles to WebAssembly?
Exactly. Pyodide has builds for Pydantic Core and for things like NumPy—basically all of the popular binary libraries. You're compiling Rust to WebAssembly and calling that shared library from Python. It's unbelievably complicated, but it works.
Staying on graphs a little bit longer, I wanted to get to some of the other features in Pydantic AI. I see in your docs that there are 4 levels of agents: single agents, agent delegation, programmatic agent handoff—which seems to be what OpenAI Swarm would be—and graph-based control flow. Would you say those are the mental hierarchy of how these things work?
Roughly.
You had some expression around OpenAI Swarm.
OpenAI has gotten in touch with me and basically said—maybe I'm not supposed to say this—that Pydantic AI looks like what Swarm would become if it were production-ready.
That makes sense. The desire to give people the same feeling they were getting from Swarm led us to implement graphs. My initial answer—just call the next agent with Python code—wasn't satisfactory to people, so we needed a better answer. That led us to graphs.
It's a minimal viable graph in some sense. What are the shapes of graphs that people should know?
I think Anthropic did a very good public service, and was surprisingly influential, with its blog post “Building effective agents.” We actually have the authors coming to speak at my conference in New York, which I think you're giving a workshop at.
I'm trying to work it out, but yes.
Tell me if you're not, but I think so.
I'm curious whether you have community names or a top 5 set of patterns or graphs.
I don't have a top 5 set of graph patterns. I would love to see what people are building with them, but it's only been a couple of weeks. Because they're relatively unopinionated about what you can do with them, they don't have the structure to support specific names as much as some other systems do.
Our agents—which have a name, although I can't remember what it is—are basically a system of deciding which tool to call, going back to the center, deciding which tool to call, going back to the center, and then exiting. That's one form of graph. Our agents are effectively one implementation of a graph, which is why they're now using graphs under the hood.
It will be interesting to see over the next few years whether we end up with predefined graph names or graph structures, whether it's just, “I built a graph,” or whether graphs don't match people's mental image of what they want and die away. We'll see.
There's always an appeal to this. Every developer eventually gets graph religion and says, “Everything is a graph.” Then they probably over-rotate and go too far into graphs, learn a whole bunch of DSLs, and say, “Actually, I didn't need this,” before scaling back.
I'm at the beginning of that process. I'm currently a graph maximalist, although I can't say I've put any of them into production yet.
This also has philosophical connections with work coming out of UC Berkeley on compound AI systems. I don't know if you know or care about that. This is the Gartner world of things, where they need some kind of industry terminology to sell it to enterprises.
I probably should know about it. I should probably get better at selling to enterprises, but no, I don't know about that stuff yet.
The argument is that instead of putting everything in one model, you have more control and potentially more observability if you break everything out into small models and compose them together. Obviously, then you need an orchestration framework to do that.
It makes complete sense. One of the things we've seen with agents is that they work well when they work well, but when they go wrong, even if you have the observability through Logfire to see what was going on, you don't have a nice hook point to say, “Hang on, this has all gone wrong.”
You have a relatively blunt instrument: erroring when you exceed some kind of limit. What you need to be able to do is iterate through these runs so that you can have your own control flow. You can say, “Okay, we've gone too far.”
That's one of the neat things about our graph implementation. You can call the next node in a loop rather than just running the full graph, so you have the opportunity to break out of it.
I'll drop one thing here. We're not going to resolve this, but then we can move on to the next thing. The common way that we developers talk about this is that machine-learning researchers look at us and laugh. They just train a bigger model and wipe us out in the next training run.
There's a certain amount of us fighting the bitter lesson. We're fighting AGI, and when AGI arrives, all of this will obviously go away. On Latent Space, we don't really discuss that because AGI is a hand-wavy concept that isn't super relevant. But we have to respect that you could do chain-of-thought with graphs and manually orchestrate a graph that reflects, thinks about whether you need more inference-time compute, thinks again, and scales that up—or you could train Strawberry into DeepSeek R1.
I saw someone saying recently that they were really optimistic about agents because models are getting faster exponentially. I took a certain amount of self-control not to explain that it wasn't exponential.
My main point was that if models are getting faster as quickly as you say they are, then we don't need agents or any of these abstraction layers. We can just give the model access to the internet, cross our fingers, and hope for the best.
Agents, agent frameworks, and graphs are basically making up for the fact that, right now, models aren't that clever. It's the same as if you're running a customer-service business and have lots of people answering telephones: the less well-trained they are, the less you trust them, and the more you need to give them a script.
If you're running a bank and have lots of customer-service people you don't trust that much, you tell them exactly what to say. If you're doing high-net-worth banking, you employ people you think are going to be charming to other rich people and send them off to have coffee with people.
The same is true of models. The more intelligent they are, the less we need to tell them how to structure what they do and constrain the routes they take.
I'm happy to move on. There are other parts of Pydantic AI worth commenting on, and this is my last rabbit hole, I promise. Obviously, every framework needs to have its model-adapter layer so that you can easily swap from OpenAI to Claude to Grok.
You also have Google Generative Language API, which I didn't really know about until I saw it in your docs. That's the Generative Language API. I assume that's AI Studio?
Yes. Google doesn't have good names for these things. Vertex is very clear, and that seems to be the API that some of the others use. Vertex is fine, but the Generative Language API returns a 503 about 20% of the time.
We have another example of going the extra mile in engineering: on every commit to main, we run tests against the live models. Not many tests, but a handful of them. Last week, GLA 1 was failing every single run—one of the tests would fail. We may even have commented that one out for now.
All of the models fail more often than you might expect, but that one seems to be particularly likely to fail. Vertex uses the same API but is much more reliable.
My argument is that versions of this appear in LangChain, and every framework has to have its own version of this. I would much rather you adopt a layer like LiteLLM, or in JavaScript, Portkey. That's their job. They focus on that one thing and normalize the APIs for you. All new models are automatically added, and you don't have to duplicate this inside your framework.
For example, if I wanted to use DeepSeek, I'd be out of luck because Pydantic AI doesn't have DeepSeek yet.
It does.
Okay, but you know what I mean. Should this live in your code, or should it live in a layer that's more like an API gateway—a defined piece of infrastructure that people have?
If a company respected by everyone had come along and done this at the right time—if it had said, “We're going to be the universal AI layer”—that would have been a credible thing to do. I've heard varying reports about whether LiteLLM is the truth, and it didn't seem to have exactly the type safety we needed.
Also, as I understand it—and I haven't looked into it in great detail—part of its business model is proxying requests through its own system to generalize them. That would be an enormous put-off for an awful lot of people.
Honestly, I don't think it's that much work to unify the models. I understand your point, but I think everyone is centralizing around the OpenAI API as the standard. DeepSeek supports that, Grok supports that, and Ollama supports that.
If there is a universal library right now, it's more or less the OpenAI SDK. It's very high quality, well typed, and uses Pydantic, so I'm biased, but I think it's pretty well respected.
There are different ways to do this because it's not just about normalizing the APIs. You also have to do secret management and all that stuff. There's also Vertex and Bedrock, which, to one extent or another, host multiple models. They don't unify the API, but they do unify—or at least, as I understand it, they unify—the model hosting. We're halfway through doing Bedrock, so I don't know it that well.
I'm surprised they don't unify the API. That seems like something I would do.
I guess the other side of model routing and picking models is evals. How do you figure out which one you should be using? I know you have very good support for mocking in unit tests, which a lot of other frameworks don't do.
My favorite Ruby library is VCR because it lets me store HTTP requests and replay them. I'll skip that part. You also have this test-model approach, where you try to figure out what the model might respond through Python without actually calling the model, and the function-model approach, where people can customize outputs. Any other fun stories from there, or is it just what you see is what you get?
On those two, I think what you see is what you get. On evals, watch this space. It's something we are going to be working on soon.
I was cynical about it for some time, and I still have some cynicism about some of the things called evals. It's unfortunate that so many different things are called evals. It would be nice if we could agree on what they are and what they aren't.
But it's an important space, and it's something we're going to be working on in both Pydantic AI and Logfire to support better. It's an unsolved problem.
You say in your docs that anyone who claims to know for sure exactly how your eval should be defined can safely be ignored.
I was thinking about vibe evals, which are what you do when you're building. You can't really test that many times to get statistical significance. Then there are production evals. You also have Logfire, which is your observability product. I tried it before, and it's very nice.
What are some of the learnings from building an observability tool for LLMs? As people think about evals, what are the right things to measure, and how many samples do you need before you can start making decisions?
I'm not the best person to answer that, so I'm not going to tell you that I know the answer to the exact number of samples. We can do back-of-the-envelope statistical calculations and work out that having 30 probably gives you most of the statistical value of having 200, for 15% of the work. But the exact question of how many examples you need is much harder to answer because it's deep within how models operate.
One of the reasons we built Logfire the way we did, allowing you to write SQL directly against your data, is precisely because we know we don't know the answers. Allowing people to innovate on how they're going to consume and process that data is valuable.
Even if we offer an eval framework on top of Logfire, it won't be right in all regards. We want people to be able to innovate. Being able to write your own SQL, connect to the API, and query the data like a database allows people to innovate—and it allows us to do the same thing.
We do a bunch of testing by writing SQL directly against Logfire, as any user could.
The other really interesting thing in observability is that OpenTelemetry is centralizing around semantic conventions for GenAI. It's a relatively new project, and a lot of it is still being added, but the idea is to unify how SDKs and agent frameworks send observability data to any OpenTelemetry endpoint.
That unification allows us to compare different libraries and models much better. The work is at a very early stage. One of the things we're going to be working on soon is implementing those semantic conventions properly. I suspect Pydantic AI will be the first agent framework to do that because we control Pydantic AI and can say that it's important for observability.
Most of the other agent frameworks aren't maintained by people trying to do observability, with the exception of LangChain, which has its own observability platform. They chose not to go down the OpenTelemetry route, so they're plowing their own furrow and are even further away from standardization.
Can you give us a quick overview of how OpenTelemetry fits into the AI workflow? There's the question of whether a trace and a span represent an LLM call, an agent, or the broader thing you're tracking.
There was a pull request from someone at IBM talking about remote agents and trying to support that concept within GenAI. I'm not particularly compelled by that because I don't think it's the common use case, but I suppose it's fine for it to be there.
The majority of the work is defining how you instrument a given call to an LLM: the actual LLM call, what data you would send to your telemetry provider, and how you would structure that data. Apart from the slightly odd remote-agent work, most of the agent-level considerations haven't yet been implemented or decided.
There's some ambiguity, but what's good about OpenTelemetry is that you can ultimately send whatever attributes you like.
If you think about observability traditionally, everyone would say that observability data is important and must be kept safe. But companies work very hard to ensure that nothing too sensitive ends up in their observability data.
If you're a doctor in a hospital and you search for a drug for an STI, the SQL might be sent to the observability provider, but none of the parameters would be. It wouldn't have the patient number, the patient's name, or the drug. With GenAI, that distinction doesn't exist because everything is mixed together in the text.
If that same patient asks an LLM which drug they should take or how to stop smoking, you can't extract the personally identifiable information and not send it to the observability platform. The sensitivity of the data that's going to end up in observability platforms will be a different order of magnitude from what you would normally send to Datadog.
Of course, you can make a mistake and send someone's password or card number to Datadog, but that would be seen as a mistake. In GenAI, a lot of data is going to be sent. I think that's why companies like LangSmith and others are trying to offer observability on-premises.
There are companies that are happy for Datadog to be cloud-hosted but want self-hosting for GenAI observability.
Is that what you're doing today? In each span, you have the number of tokens and the context. Are you storing everything and then going to offer self-hosting for the platform?
We offer scrubbing roughly equivalent to what the other observability platforms have. If we see “password” as the key, we won't send the value. But as I said, that doesn't really work in GenAI. We're accepting that we'll have to store a lot of data, and then we'll offer self-hosting for the people who can afford it and need it.
This is the first time that most workloads' performance depends on a third party. If you're looking at Datadog data, it's usually your application driving latency, memory usage, and all of that. Here, you can have spans that take a long time because the Generative Language API isn't working or because OpenAI is overwhelmed.
Do you do anything there? Since the provider is effectively the same across customers, are you trying to surface these things for people and say, “This was a very slow span, but all customers using OpenAI right now are seeing the same thing, so maybe don't worry about it”?
We do a few things that people don't generally do in OpenTelemetry. We send information at the beginning of a span—as well as when it finishes. By default, OpenTelemetry only sends you data when the span finishes.
If you think about a request that might take 20 seconds, even if some of the intermediate spans finished earlier, you can't place them on the page until you get the top-level span. If you're using standard OpenTelemetry, you can't show anything until those requests are finished.
When requests take a few hundred milliseconds, it doesn't really matter. But when you're making GenAI calls or running a batch job that might take 30 minutes, that latency in seeing the span is crippling for understanding your application. We've done some slightly complex work to send data about a span as it starts.
What are your thoughts on everyone else trying to build on top of OpenTelemetry in different languages? There's the OpenTelemetry project, which doesn't exactly roll off the tongue. How do you see the future of these tools? Is everybody going to have to build their own OpenTelemetry observability layer to sell?
We're not going to instrument the OpenAI SDK with the new semantic conventions because, at some point, that's going to happen and live inside OpenTelemetry. We might help with it, but we're a tiny team and don't have time to do all of that work.
OpenTelemetry is an interesting project, but I suspect that eventually most of the semantic instrumentation of the major SDKs will live inside the main OpenTelemetry repositories.
What happens with the agent frameworks, and what data you need at the framework level to get the context, is unclear. I don't think we know the answer yet.
I was on an OpenTelemetry call last week talking about GenAI. Someone from Arize was talking about the challenges they have trying to get OpenTelemetry data out of LangChain, where it's not natively implemented. They're having a tough time.
I hadn't realized this before, but we're lucky to primarily be talking about our own agent framework, where we have control, rather than trying to instrument other people's.
I actually didn't know about this semantic-conventions project. It looks like it's merged into the main OpenTelemetry repository. What should people know about it? I had never heard of it before.
I think it looks like a great start. There are some unknowns around how you send the messages that go back and forth, which is the most important thing of all. That has moved out of attributes and into OpenTelemetry events.
OpenTelemetry events, in turn, are moving from being on a span to being their own top-level API where you send data. There's still a lot of churn going on.
I'm impressed by how fast the OpenTelemetry community is moving on this project. Everyone understands that it's important, and people are crying out for instrumentation, so I'm pleasantly surprised at how quickly it's moving.
I'm just browsing through the specifics. I can already see that this basically bakes in whatever the previous paradigm was, so now they have, like, GenAI...
GenAI usage: prompt tokens and completion tokens, and obviously now we have reasoning tokens as well. Then there’s only 1 form of sampling, which is top_p. You’re basically baking in, or sort of reifying, things that you think are important today, but it’s not a super foolproof way of doing this for the future.
Yeah, I mean, that’s what’s neat about OTel: you can always go and send another attribute, and that’s fine. It’s just that there are a bunch that are agreed on. To come back to your previous point about whether or not we should be relying on 1 centralized abstraction layer, this stuff is moving so fast that if you start relying on someone else’s standard, you risk basically falling behind because you’re relying on someone else to keep things up to date, or you fall behind because you’ve got other things going on.
Yeah, yeah, that’s fair. That’s fair. Any other observations just about building Logfire? Actually, let’s just talk about this: you announced Logfire. I was kind of only familiar with Logfire because of your Series A announcement. I actually thought you were making a separate company. I remember some amount of confusion with you when that came out.
So, to be clear, it’s Pydantic Logfire, and the company is 1 company that has kind of 2 products: an open-source thing and an observability thing, correct? I was just kind of curious: any learnings building Logfire? The classic question is, do you use ClickHouse? Is this the standard persistence layer? Any learnings doing that?
We don’t use ClickHouse. We started building a database with ClickHouse, moved off ClickHouse onto Timescale, which is a Postgres extension for analytical databases, and then moved off Timescale onto DataFusion. We’re basically now building—it’s DataFusion, but it’s kind of our own database. Bill is not entirely happy that we went through 3 databases before we chose 1. I’ll say that, but we’ve got to the right one in the end, I think.
We could have realized that Timescale wasn’t right. I think ClickHouse and Timescale both taught us a lot, and we’re in a great place now, but it’s been a real journey on the database in particular.
Okay, so as a database nerd, I have to double-click on this. ClickHouse is supposed to be the ideal backend for anything like this, and then moving from ClickHouse to Timescale is another counterintuitive move that I didn’t expect, because Timescale was an extension on top of Postgres, not super meant for high-volume logging. Tell us those decisions.
At the time, ClickHouse did not have good support for JSON. I was speaking to someone yesterday who said ClickHouse doesn’t have good support for JSON and got roundly stepped on because apparently it does now, so they’ve obviously gone and built their proper JSON support. But back when we were trying to use it, I guess a year ago or a bit more than a year ago, everything happened to be a map, and maps are a pain to try and do when looking up JSON-type data.
Obviously, all these attributes, everything you’re talking about there in terms of the GenAI stuff, you can choose to make them top-level columns if you want, but the simplest thing is just to put them all into a big JSON pile, and that was a problem with ClickHouse.
ClickHouse also had some really ugly edge cases. By default, or at least until I complained about it a lot, ClickHouse thought that 2 ns was longer than 1 second because they compared intervals just by the number, not the unit. I complained about that a lot, and then they caused it to raise an error and just say you have to have the same unit. Then I complained a bit more, and eventually, I think, as I understand it now, they convert between units.
But stuff like that, when a lot of what you’re doing is comparing the duration of spans, was really painful. Also, things like you can’t subtract 2 datetimes to get an interval; you have to use the date sub function.
The fundamental thing is that because we want our end users to write SQL, the quality of SQL—how easy it is to write—matters way more to us than if you’re building a platform on top where your developers are going to write the SQL, and once it’s written and it’s working, you don’t mind too much. I think that’s 1 of the fundamental differences.
The other problem that I have with ClickHouse and, in fact, Timescale is that the ultimate architecture—the Snowflake architecture of big data in object storage queried with some kind of cache from nearby—they both have it, but it’s closed source and you only get it if you go and use their hosted versions.
So even if we had got through all the problems with Timescale or ClickHouse, we would end up with them wanting to take their 80% margin, and then we would be wanting to take our own margin. That would basically leave us less space or margin.
Whereas DataFusion is properly open source. All of that same tooling is open source, and for us as a team of people with a lot of Rust expertise, DataFusion, which is implemented in Rust, means we can literally dive into it and go and change it.
For example, I found that there were some slowdowns in DataFusion’s string-comparison kernel for doing things like string contains. It’s just Rust code, and I could go and rewrite the string-comparison kernel to be faster. Or, for example, DataFusion, when we started using it, didn’t have JSON support. Obviously, as I’ve said, that’s something we needed. I was able to go and implement that in a weekend using the JSON parser that we built for pydantic-core.
So it’s the fact that DataFusion is, for us, the perfect mixture of a toolbox to build a database with, not a database, and we can go and implement stuff on top of it in a way that, if you were trying to do that in Postgres or in ClickHouse—I mean, ClickHouse would be easier because it’s C++, relatively modern C++, but as a team of people who are not C++ experts, that’s much scarier than DataFusion for us.
Yeah, that’s a beautiful rant. It’s funny: most people don’t think they have agency on these projects. They’re kind of like, “Oh, I should use this or I should use that.” They’re not really like, “What should I pick so that I contribute the most back to it?”
But I think you obviously have an open-source-first mindset, so that makes a lot of sense.
I think if we were a better startup and faster-moving, and just headlong determined to get in front of customers as fast as possible, we should have just started with ClickHouse.
I hope that long term we’re in a better place for having worked with DataFusion. We’re quite engaged now with the DataFusion community. Andrew Lamb, who maintains DataFusion, is an advisor to us. We’re in a really good place now, but yeah, it’s definitely slowed us down relative to just building on ClickHouse and moving as fast as we can.
Okay, we’re about to zoom out and do Pydantic Run and all the other stuff, but my last question on Logfire is really: at some point, you run out of community goodwill just because, like, “Oh, I use Pydantic, I love Pydantic, I’m going to use Logfire.” Then you start entering the territory of Datadog, Sentry, and Honeycomb.
Where are you going to really spike here? What’s the differentiator?
I wasn’t writing code in 2001, but I’m assuming that there were people talking about web observability, and then web observability stopped being a thing—not because the web stopped being a thing, but because all observability had to do with the web.
If you were talking to people in 2010 or 2012, they would have talked about cloud observability. Now that’s not a term because all observability is cloud-first. The same is going to happen to GenAI.
So whether or not you’re trying to compete with Datadog or with Arize and LangSmith, you’ve got to do first-class—you’ve got to do general-purpose observability with first-class support for AI. As far as I know, we’re the only people really trying to do that.
I mean, I think Datadog are starting in that direction, and to be honest, I think Datadog is a much scarier company to compete with than the AI-specific observability platforms. In my opinion—and I’ve also heard this from lots of customers—AI-specific observability where you don’t see everything else going on in your app is not actually that useful.
Our hope is that we can build the first general-purpose observability platform with first-class support for AI, and that we have this open-source heritage of putting developer experience first that other companies haven’t done.
For all that I’m a fan of Datadog and what they’ve done, if you search “Datadog logging Python” and you just try, as a non-observability expert, to get something up and running with Datadog and Python, it’s not trivial. That’s something Sentry has done amazingly well, but there’s enormous space in most of observability to do DX better.
Since you mentioned Sentry, I’m curious how you thought about licensing and all of that. Obviously, Pydantic is MIT-licensed. You don’t have any rolling license like Sentry has, where you can only use an open-source, 1-year-old version of it. Was that a hard decision?
To be clear, Logfire is closed source, so Pydantic and PydanticAI are MIT-licensed and properly open source, and then Logfire, for now, is completely closed source.
In fact, the struggles that Sentry have had with licensing, and the weird pushback the community gives when they take something that’s closed source and make it source-available, just meant that we avoided that whole subject matter.
I think the other way to look at it is, in terms of either headcount or revenue or dollars in the bank, the amount of open source we do as a company—we’ve got to be up there with the most prolific open-source companies, per head. So we didn’t feel like we were morally obligated to make Logfire open source.
We have Pydantic. Pydantic is the foundational library in Python, and PydanticAI is our contribution to open source. Then Logfire is openly for-profit, and we’re not claiming otherwise. We’re not trying to walk a line where it’s open source, but we’re really trying to make it hard to deploy so you probably want to pay us. We’re trying to be straight about that. We could change that at some point in the future, but it’s not an immediate plan.
All right. So the first one I saw—this new, I don’t know if it’s a product you’re building—pydantic.run, which is a Python browser sandbox. What was the inspiration behind that?
We talk a lot about code interpreters for LLMs. I’m an investor in a company called E2B, which is code sandboxes as a service for remote execution. What’s the pydantic.run story?
Pydantic Run is again completely open source. I have no interest in making it into a product. We just needed a sandbox to be able to demo Logfire in particular, but also PydanticAI. It doesn't have it yet, but I'm going to add basically a proxy to OpenAI and the other models, so that you can run PydanticAI in the browser, see how it works, tweak the prompt, et cetera. We'll have some kind of per-day limit on what you can spend on it, or on what the spend is.
The other thing we wanted to be able to do was, when you log in to Logfire, we have quite a lot of drop-off. A lot of people sign up, find it interesting, and then don't go and create a project. My intuition is that they're like, "Oh, okay, cool, but now I have to go and open up my development environment, create a new project, do something with the right token. I can't be bothered." Then they drop off and forget to come back.
I think that happens to all of us. I started seeing if I could do it a week and a half ago, got something to run, and then ended up improving it. Suddenly, I spent a week on it, but I think it's useful.
Yeah, I remember maybe 2 or 3 years ago there were a couple of companies trying to build browser terminals exactly for this. You go on GitHub, see a project that's interesting, but then you have to clone it and run it on your machine, and sometimes it can be sketchy. This is cool, especially since you already make all the docs runnable, like you said—you kind of test them. It sounds like you might just have—
Yeah, so the plan is that on every example in PydanticAI, there's a button that basically says "Run," which takes you into pydantic.run. It has that code there, and depending on how hard we want to push, we could also have it hooked up to Logfire automatically. There's a, "Hey, just come and join the project," and you can see what that looks like in Logfire.
That's super cool. I think one of the biggest personal drop-offs from open-source projects is that it's kind of like, "Do this," and as soon as something doesn't work, I just drop off. It takes some discipline.
There have been many versions of this that I've been through in my career where you had to extract this code and run it, and it always falls out of date. Often, we would have this concept of transclusion, where we have a separate code-examples repo that gets pulled into our docs, and it never really works. It takes a lot of discipline, so kudos to you on this.
It was years of maintaining Pydantic and people complaining, "Hey, that example's out of date," before we eventually went and built pytest-examples, which is one of the hardest-to-search-for open-source projects we've ever built. Obviously, if you search for pytest-examples, you get examples of how to use pytest.
Pytest-examples will basically go through both your code inside your docstrings to look for Python code and the Markdown in your docs, extract that code, then run it for you, run linting over it, and soon run type checking over it. That's how we keep our examples up to date.
Now we have hundreds of examples, all of which are runnable and self-contained. If they refer to the previous example, they're already structured so that they have to be able to import the code from the previous example. Why don't we give someone a nice place to actually run that using OpenAI and see what the output is?
Lovely. All right, so that's kind of my take in the notes here. I just like going through people's X accounts, not Twitter. For 4 years, you've been saying we need a plain-text successor to Jupyter notebooks.
Yeah, I think people may have gone the other way, which is to make it even more opinionated, like with AI and all these kinds of notebook companies.
Well, yes. In reply to that, someone replied and said, "Marimo is that." Sure enough, Marimo is really impressive. I've subsequently spoken to the Marimo guys and got to angel-invest in them. I can't remember—I think it's CRV.
Marimo is very cool. Its notebooks also run in the browser, again using Pyodide.
In fact, I nearly didn't build pydantic.run because we were just going to use Marimo. My concern was that people would think Logfire was only to be used in notebooks. I wanted something that, ironically, felt more basic—more like a terminal—so no one thought it was just for notebooks.
Yeah, there's a lot of notebook hate out there. I have very strong opinions about proper notebooks—not like Jupyter notebooks. The idea that you have to run the cells in the right order, and a whole bunch of other things, is basically worse than Excel, or similarly bad to Excel.
Oh, so you are a notebook hater, then, and invested in a notebook?
I have this rant called "Notbook," which was my attempt to build an alternative, but mostly just a rant about the 10 reasons why notebooks are just as bad as Excel.
But Marimo and all the new ones that are text-based at least solve a whole bunch of those problems.
I agree with that.
Yeah, I was kind of wishing for something like a better notebook, and then I saw Marimo. I was like, "Oh, yeah, these guys are ahead of me on this."
I don't know if I would do the sort of annotation-based thing. A lot of people love the "annotate this function and it just adds magic" approach. Similarly to what Jeremy Howard does with his stuff, it seems a little bit too magical still, but hey, it's a big improvement from notebooks.
Yeah, yeah, great. Just as with LLM usage, the .ipynb file is just not good to put in LLMs.
True, it's really not. They freak out. They're not good to put in Git either.
I mean, okay, well, we'll kill .ipynb at some point.
Any other takes? I was going to ask you just about the London scene. What's it like building out there?
I'm an evening person. The good thing is that I can get up late and then work late because I'm speaking to people in the US a lot of the time. I got invited earlier today to a drinks reception about AI at 10 Downing Street with the prime minister, so I'm feeling positive about the UK right now and AI.
But I think, like everywhere, everyone in the US and China knows that we're way behind on AI. I think it's good that the UK is beginning to say this is an opportunity, not just a risk.
I keep being told I should be at more events, hanging out with AI people more. My instinct is that I'd rather sit at my computer and write code. I think that's probably a more effective way of getting people's attention. Part of me thinks I should be sitting on Twitter, not in San Francisco chatting to people. I think it's probably a bit of a mixture, and I could probably do with being in the States a bit more. I think I'm going to be over there a bit more this year.
There's definitely a risk if you're somewhere where everyone wants to chat to you about code, but you don't write any code. That's a fail.
I would say definitely. There's a scene, and one way to really fail at this is to just be involved in that scene and have it eat up your time. But be at the right events, and the ones that I'm running are good events, hopefully.
Okay, come to AI Engineer. What I say is, use those things to produce high-quality content that travels in a different medium than you normally would be able to, because there's some selectivity and a focused community around that thing. People will discover your work more, and it will be highly produced. That's the pitch for why I do conferences, at least.
In terms of talking to people, I always think about this as a 3-strikes rule. After a while it gets repetitive, but maybe the first 10 or 20 conversations you have with people—if the same stuff keeps coming up, that's an indication that people want a thing. It helps you prioritize in a more long-form way than you can get in shallow interactions online.
That in-person, eye-to-eye, "This is my pain at work," and you see the pain and you're like, "Oh, okay, if I do this for you, you will love our tool"—you can't really replace that.
It's customer interviews, really.
Yeah, I agree entirely with that. I think you're right on a lot of that. It's very easy to get distracted by what people are saying on Twitter and LinkedIn. That's another thing that's very hard to correct for: which of those people are actually building this stuff in production at serious companies, and which of them are on day 4 of learning to code?
They have equally strident opinions, and in a few characters they seem equally valid. But which one is real and which one isn't—or which one is from someone who really knows their stuff—is hard to know.
Anything else, Sam? What do you want to get off your chest?
Nothing in particular. I've really enjoyed our conversation. I would say that if anyone has looked at PydanticAI, we know it's not complete yet. We know there are a bunch of things missing—embeddings, storage, MCP, toolsets, and stuff like that. We're trying to be deliberate and do stuff well, and that involves not being feature-complete yet. But keep coming back and looking in a few months, because we're pretty determined to get there.
Whether or not you think AI is going to be the next Excel, the next internet, or the next Industrial Revolution, it's going to affect all of us enormously. As a company, we get that making PydanticAI the best agent framework is existential for us.
You're also the first serious AI company I've seen that has no open roles for now. Every founder who comes on our podcast—the go-to action is, "Please come work with us."
We're not hiring right now. I would love, bluntly, for Logfire to have a bit more commercial traction and a bit more revenue before I hire more people. It's quite nice having a few years of runway, not a few months of runway, so I'm not in any great appetite to destroy that runway overnight by hiring another 10 people, even if the whole team is rushed off its feet doing, as you said, 3–4 startups at the same time.