ExportXMLWordPrintableJSON

    • Type: Improvement
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: ABX
    • None
    • Python Drivers
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?
    • None
    • None
    • None
    • None
    • None
    • None

      TL;DR

      Add a MongoDB-backed persistence option to the llama-agents workflow server so users can run a durable WorkflowServer on MongoDB, the same way they can today on SQLite or Postgres. This is a single, self-contained addition to the llama-agents-server package: one new store class that implements the existing persistence interface, plus MongoDB driver-handshake metadata so the usage is identifiable in server-side telemetry.

      Context

      What the product is. llama-agents is an open-source framework for building and running AI agent workflows (event-driven, async Python programs). The llama-agents-server package wraps a workflow as a web service (WorkflowServer) that exposes it over HTTP. To survive process restarts, the server persists its runtime data to a database.

      Concepts you need (defined before use):

      • Workflow run — one execution of a workflow, identified by a run_id.
      • Handler — the server-side record tracking a run's status (running, completed, failed), its result, and timestamps.
      • Event — a message the workflow emits during a run. Events form an ordered log per run (a monotonic sequence number), which the server replays and streams to clients.
      • Tick — one step of the workflow's internal execution loop, also stored as an ordered log per run.
      • State store — a per-run key/value store holding the workflow's own Context state (serialized as JSON), separate from the event/tick logs.
      • Workflow store — the umbrella persistence backend that owns all of the above (handlers + events + ticks + per-run state stores). This is the pluggable piece.

      The problem. Today the framework can persist to SQLite (single-process) or Postgres (via the DBOS runtime, for distributed/production). It cannot use MongoDB. There is a clean, documented extension point — an abstract base class every backend implements — but no MongoDB implementation ships. Users who standardize on MongoDB currently cannot back the workflow server with it.

      Desired User Experience

      The following four scenarios show what a user writes today versus what they should be able to write once this ticket ships. In every case, only the store construction line changes; the rest of the app is identical.

      Scenario 1 — Ephemeral (no change; shown for baseline).

      from llama_agents.server import WorkflowServer
      
      # No workflow_store -> in-memory (MemoryWorkflowStore); state lost on restart.
      server = WorkflowServer()
      server.add_workflow("greet", greet_wf)
      

      Scenario 2 — Durable, single process.

      # BEFORE — the only zero-setup durable option is a local SQLite file
      from llama_agents.server import WorkflowServer, SqliteWorkflowStore
      
      store = SqliteWorkflowStore(db_path="workflows.db")   # local file on disk
      server = WorkflowServer(workflow_store=store)
      server.add_workflow("greet", greet_wf)
      
      # AFTER — the same durability, but backed by MongoDB
      from llama_agents.server import WorkflowServer, MongoWorkflowStore
      
      store = MongoWorkflowStore(                             # store owns the connection
          uri="mongodb://localhost:27017",
          database="llama_agents",
      )
      server = WorkflowServer(workflow_store=store)
      server.add_workflow("greet", greet_wf)
      # ^ Only the store line changed. Handlers, events, ticks, and per-run
      #   Context state now persist to MongoDB and survive a restart.
      

      Scenario 3 — Production / distributed (multiple server replicas sharing one database).

      # BEFORE — the only shared-database option is Postgres via the DBOS runtime
      from dbos import DBOS
      from llama_agents.dbos import DBOSRuntime
      from llama_agents.server import WorkflowServer
      
      DBOS(config={
          "name": "my-app",
          "system_database_url": "postgresql://user:pass@localhost:5432/mydb",
          "run_admin_server": False,
      })
      runtime = DBOSRuntime()
      server = WorkflowServer(
          workflow_store=runtime.create_workflow_store(),
          runtime=runtime.build_server_runtime(),
      )
      server.add_workflow("greet", greet_wf)
      
      # AFTER — a MongoDB deployment (e.g. a replica set) shared by multiple replicas,
      #         without pulling in DBOS/Postgres at all
      from llama_agents.server import WorkflowServer, MongoWorkflowStore
      
      store = MongoWorkflowStore(
          uri="mongodb://user:pass@host1:27017,host2:27017/?replicaSet=rs0",
          database="llama_agents",
      )
      server = WorkflowServer(workflow_store=store)
      server.add_workflow("greet", greet_wf)
      # ^ Every replica constructs the same store pointing at the same database;
      #   they share handler/event/tick state, matching today's shared-Postgres story.
      

      Scenario 4 — Bring-your-own client (reuse an existing connection).

      # AFTER — inject a pre-built client the app already owns
      from pymongo import AsyncMongoClient
      from llama_agents.server import WorkflowServer, MongoWorkflowStore
      
      client = AsyncMongoClient("mongodb://localhost:27017")   # caller owns this client
      
      store = MongoWorkflowStore(client=client, database="llama_agents")
      server = WorkflowServer(workflow_store=store)
      # ^ The store reuses the caller's client and does NOT override its handshake
      #   metadata. (When the store is given a `uri` instead, it creates its own
      #   client and stamps a component-distinct driver name on it — see AC below.)
      

      Task

      Goal:

      Let users run the llama-agents workflow server on MongoDB, just like they can on SQLite or Postgres today — for both single-server and multi-server setups — so teams already on MongoDB don't need a second database.

      Where:

      (Product) Acceptance Criteria

      References

      MongoDB documentation (required reading for the implementation):

      • PyMongo async driver — AsyncMongoClient — the async client the store constructs (or receives) for all reads/writes.
      • MongoDB handshake spec — wrapping-library metadata — the contract behind the "attributable in telemetry" criterion; defines how a wrapping library appends a component-distinct driver name during the handshake.
      • PyMongo DriverInfo — the API used to stamp that driver name onto a store-created client (leave an injected client's metadata untouched).
      • MongoDB change streams — the native mechanism to consider for live event streaming (the alternative to polling), analogous to Postgres LISTEN/NOTIFY in the reference store.
      • Unique indexes — for enforcing the per-run monotonic sequence on events/ticks, mirroring the unique-constraint retry logic in the SQL stores.

      Additional in-repo code (not linked above):

      • _pool.py — the PoolProvider ownership abstraction (create vs. borrowed) that PostgresWorkflowStore uses to decide whether it owns or reuses a connection; the model for MongoDB's uri-owns vs. client-injected split.
      • memory_workflow_store.py — the in-memory reference backend, including its condition-based (non-polling) subscribe_events override worth mirroring for live streaming.
      • WorkflowServer (server.py) — where workflow_store is injected, confirming there is no connection-string dispatcher to modify.
      • state_store.py (SDK protocol) — the per-run Context state protocol the store's state-store companion must satisfy; defined in llama-index-workflows and requires no change.

       

            Assignee:
            Casey Clements
            Reporter:
            Raschid Jimenez
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: