惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
The Blog of Author Tim Ferriss
宝玉的分享
宝玉的分享
The Register - Security
The Register - Security
D
Docker
The Cloudflare Blog
A
About on SuperTechFans
Microsoft Security Blog
Microsoft Security Blog
Recent Announcements
Recent Announcements
月光博客
月光博客
B
Blog RSS Feed
博客园 - 【当耐特】
The GitHub Blog
The GitHub Blog
B
Blog
IT之家
IT之家
美团技术团队
Engineering at Meta
Engineering at Meta
C
Check Point Blog
云风的 BLOG
云风的 BLOG
Last Week in AI
Last Week in AI
G
Google Developers Blog
MongoDB | Blog
MongoDB | Blog
Microsoft Azure Blog
Microsoft Azure Blog
S
SegmentFault 最新的问题
V
V2EX
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Apple Machine Learning Research
Apple Machine Learning Research
U
Unit 42
H
Help Net Security
雷峰网
雷峰网
人人都是产品经理
人人都是产品经理
博客园 - 司徒正美
Stack Overflow Blog
Stack Overflow Blog
博客园 - Franky
PCI Perspectives
PCI Perspectives
J
Java Code Geeks
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
M
MIT News - Artificial intelligence
腾讯CDC
A
Arctic Wolf
C
CERT Recently Published Vulnerability Notes
量子位
C
CXSECURITY Database RSS Feed - CXSecurity.com
Latest news
Latest news
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
The Hacker News
The Hacker News
有赞技术团队
有赞技术团队
Schneier on Security
Schneier on Security
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
Persistent multi-agent conversations with the OpenAI Agents SDK and MongoDB
Alex Bevilac · 2026-04-28 · via DEV Community

Version 0.14.2 added a MongoDBSession backend; here's a working multi-agent customer-support demo that uses it, and the documents it leaves behind.

The OpenAI Agents SDK has shipped session backends for SQLite, SQLAlchemy, Redis, and Dapr for a while now. With 0.14.2 (April 2026), MongoDBSession joined that list, and 0.14.6 added the docs page. If you're already running MongoDB for application data, this is the moment to stop standing up a second store just to remember what the agent said three turns ago. The demo for this walkthrough is a small e-commerce support app with three handoff-connected agents and one MongoDB instance behind everything: customers, orders, support articles, and the conversation history.

Repo: https://github.com/alexbevi/mongodb-openai-agents-sdk-example.

What you'll build

A CLI customer-support agent that identifies the user from MongoDB, hands off between a triage agent, an order-support agent, and a knowledge-base agent, and persists every turn (user message, tool call, tool output, assistant reply, handoff) to MongoDB via MongoDBSession. You quit, restart the process, log in with the same email, and the agent picks up the thread — no re-explaining the return you started yesterday.

Why MongoDB for sessions

A session backend has three jobs: store one item per turn, return them in order on the next run, and not corrupt itself when two processes write at once. The interesting part for MongoDB is how naturally each of those maps to things the database already does.

Items in a session are heterogeneous. A turn can be a user message, a tool call, a tool result, an assistant message, or a handoff record — each with its own shape. A document store takes those payloads as-is. There's no messages table you have to migrate every time the SDK adds a new run-item type, and no JSON column to parse around.

Ordering is the hard part, and $inc is built for it. MongoDBSession stamps each message with a monotonically increasing seq counter — the SDK docs call this out explicitly: it preserves ordering across concurrent writers and processes. That's a single-document atomic increment, not a distributed lock or an optimistic-retry loop. Two FastAPI workers handling the same session_id won't interleave.

One store, one connection pool. This is the angle the demo actually showcases. The ecommerce_support database holds customers, orders, and support_articles next to agent_sessions and agent_messages. Tools query operational data, the SDK persists turns, and they share the same AsyncMongoClient. Adding session memory cost zero new infrastructure.

Walkthrough

1. Prerequisites

Python 3.10+, an OpenAI API key, and either a local mongod or a MongoDB Atlas cluster. Nothing in the demo requires Atlas-only features — a 27017 on localhost is fine.

2. Install

requirements.txt pins the new extra:

openai-agents[mongodb]>=0.14.2
python-dotenv>=1.0.0
pymongo>=4.13

Enter fullscreen mode Exit fullscreen mode

pip install -r requirements.txt

Enter fullscreen mode Exit fullscreen mode

The [mongodb] extra pulls in pymongo's async client; the MongoDBSession class lives at agents.extensions.memory.MongoDBSession.

3. Connect

The demo uses one shared AsyncMongoClient per process (the right pattern — sessions don't own the client, they share its pool):

from pymongo.asynchronous.mongo_client import AsyncMongoClient

MONGODB_URI = os.environ.get("MONGODB_URI", "mongodb://localhost:27017")
DB_NAME = "ecommerce_support"

mongo_client = AsyncMongoClient(MONGODB_URI)
db = mongo_client[DB_NAME]

try:
    await mongo_client.admin.command("ping")
except Exception as exc:
    print(f"\nCannot connect to MongoDB ({MONGODB_URI}):\n  {exc}")
    return

Enter fullscreen mode Exit fullscreen mode

4. Seed and identify

python seed_data.py loads three demo customers, five products, five orders with embedded line items, and seven support articles indexed for $text search. Then main.py looks the customer up so the triage agent doesn't have to ask for an email it already knows.

5. Instantiate the session

This is the integration:

session_id = f"support_{email.replace('@', '_at_').replace('.', '_')}"
session = MongoDBSession(
    session_id=session_id,
    client=mongo_client,
    database=DB_NAME,
)

if not await session.ping():
    print("Warning: MongoDB session storage is unavailable.")

existing = await session.get_items()

Enter fullscreen mode Exit fullscreen mode

Constructing with client= (rather than MongoDBSession.from_uri(...)) means the session shares the app's connection pool and session.close() becomes a no-op — the lifecycle stays with you. session.ping() is a real round-trip against MongoDB, useful for liveness probes.

6. Run

Pass session= to the runner. Everything else is the same SDK you already know:

with trace("Customer Support", group_id=conversation_id):
    result = await Runner.run(
        current_agent,
        input=user_input,
        context=ctx,
        session=session,   # MongoDB stores every turn automatically
    )

Enter fullscreen mode Exit fullscreen mode

Have a conversation, quit, run python main.py again with the same email, and the next message gets the full prior context prepended automatically.

What MongoDB actually stored

After a few turns with alice@example.com, two collections show up in the ecommerce_support database. The interesting one is agent_messages. A representative document, abridged:

{
  _id: ObjectId("6620d1f4..."),
  session_id: "support_alice_at_example_com",   // partition key for this conversation
  seq: 7,                                        // monotonically increasing turn order
  message_data: {                                // the SDK's run-item, stored as-is
    type: "function_call_output",
    call_id: "call_8b2...",
    output: "Return initiated for order ORD-1001.\nReason: Not powerful enough...\nEstimated refund: $1,484.98 (includes 10% Gold loyalty bonus)"
  },
  created_at: ISODate("2026-04-26T19:14:08.221Z")
}

Enter fullscreen mode Exit fullscreen mode

Three fields earn their keep:

  • session_id is the only field every read filters on. It's the partition key for "this conversation."
  • seq is the integer that makes ordering deterministic. The SDK reads with sort({ seq: 1 }) and writes with an atomic $inc against the matching agent_sessions document, which is what makes concurrent workers safe without a distributed lock.
  • message_data is the SDK's run-item — a user message, tool call, tool output, assistant message, or handoff. Different shape every time. The document model just stores it.

agent_sessions holds one document per session_id with the current high-water seq and timestamps — that's the counter $inc operates on.

The SDK creates its indexes on first use (per the sessions docs). You'll see a compound index on (session_id, seq) on agent_messages (the only access pattern the SDK has — fetch ordered history for one session) and a unique index on session_id in agent_sessions.

Production notes

For Atlas, swap the URI for mongodb+srv://...MongoDBSession accepts it without any other change. If abandoned conversations accumulate, add a TTL index on agent_messages.created_at and old turns retire on their own.

Connection lifetime matters: keep one AsyncMongoClient per process, construct MongoDBSession(client=...) per request, and let the Runner do the rest. Don't reach for MongoDBSession.from_uri(...) in a web handler — it builds and tears down a client every call. The session needs read/write on the two configured collections (defaults agent_sessions and agent_messages, both overridable via sessions_collection= and messages_collection=). The seq counter keeps concurrent writers safe, but fanning the same session_id across processes will interleave their turns — safe, but probably not what the user meant.

Try it yourself

git clone https://github.com/alexbevi/mongodb-openai-agents-sdk-example
cd mongodb-openai-agents-sdk-example
pip install -r requirements.txt
cp env.example .env          # set OPENAI_API_KEY and MONGODB_URI
python seed_data.py
python main.py

Enter fullscreen mode Exit fullscreen mode

Required env vars: OPENAI_API_KEY, MONGODB_URI (defaults to mongodb://localhost:27017). Demo accounts: alice@example.com (Gold), bob@example.com (Standard), carol@example.com (Platinum).

Where to go next

  • The full session API surface — get_items, add_items, pop_item, clear_session, ping — is documented in the Sessions overview, including the MongoDB-specific notes on collection naming and Atlas URIs.
  • Wrap your MongoDBSession in OpenAIResponsesCompactionSession once threads grow long; it summarizes old turns server-side and rewrites the underlying session.
  • The natural next MongoDB feature for this demo is Atlas Vector Search — store embeddings on support_articles and replace the $text query in search_knowledge_base with $vectorSearch. Same database, same client, one new index.