add moss-agent example with LiveKit voice agent integration#262
add moss-agent example with LiveKit voice agent integration#262HarshaNalluru wants to merge 1 commit into
Conversation
…sary configurations
There was a problem hiding this comment.
🚩 Example placed outside the voice-agents directory
The AGENTS.md repository layout documents LiveKit-based voice agents under examples/voice-agents/. This example is a LiveKit voice agent (imports livekit.agents, uses AgentServer, AgentSession, etc.) but is placed at examples/python-moss-agent/ instead of examples/voice-agents/python-moss-agent/. The existing two voice agent examples (airline-pnr/, mortgage-lending/) both live under examples/voice-agents/. This may be intentional since the example is specifically showcasing the moss-agent SDK rather than a general voice agent pattern, but it breaks the layout convention.
Was this helpful? React with 👍 or 👎 to provide feedback.
| return [ | ||
| DocumentInfo( | ||
| id=doc["id"], | ||
| text=doc["text"], | ||
| metadata=doc.get("metadata", {}), | ||
| ) | ||
| for doc in raw | ||
| ] |
There was a problem hiding this comment.
🔴 Integer metadata values not coerced to strings, violating DocumentInfo contract
The load_documents function at examples/python-moss-agent/create_indexes.py:47 passes metadata=doc.get("metadata", {}) directly from the parsed JSON without coercing values to strings. However, product_catalog.json contains integer-valued metadata (e.g., "price_usd": 279) on all 10 product entries. The Moss DocumentInfo type requires metadata: Optional[Dict[str, str]] — all values must be strings. The sibling example in the same repo (examples/voice-agents/airline-pnr/create_indexes.py:59-61) explicitly handles this with metadata = {k: str(v) for k, v in doc.get("metadata", {}).items()} and a comment: "Moss requires string-valued metadata. Coerce so the JSON can still write ints/bools naturally." Without this coercion, index creation for ecommerce_products will either error or silently produce incorrect metadata.
| return [ | |
| DocumentInfo( | |
| id=doc["id"], | |
| text=doc["text"], | |
| metadata=doc.get("metadata", {}), | |
| ) | |
| for doc in raw | |
| ] | |
| return [ | |
| DocumentInfo( | |
| id=doc["id"], | |
| text=doc["text"], | |
| metadata={k: str(v) for k, v in doc.get("metadata", {}).items()}, | |
| ) | |
| for doc in raw | |
| ] | |
Was this helpful? React with 👍 or 👎 to provide feedback.
| # Ecommerce Support Voice Agent | ||
|
|
||
| End-to-end LiveKit voice agent built on the | ||
| [`moss-agent`](https://github.com/usemoss/moss/tree/main/python/moss-agent) |
There was a problem hiding this comment.
🚩 README links to non-existent python/moss-agent directory
The README at line 4 links to https://github.com/usemoss/moss/tree/main/python/moss-agent, but there is no python/ directory at the repository root (and no moss-agent subdirectory anywhere in the repo). This link will 404. If the moss-agent SDK lives in an external repo or hasn't been merged yet, the link should be updated to point to the correct location (e.g., a PyPI page or the actual repo path once it exists).
Was this helpful? React with 👍 or 👎 to provide feedback.
| ) | ||
| from livekit.plugins import cartesia, deepgram, openai, silero | ||
|
|
||
| from moss_agent import MossAgent, MossCall, QueryOptions |
There was a problem hiding this comment.
🚩 Uses moss-agent SDK not yet present in this repository
Both agent.py and create_indexes.py import from moss_agent (MossAgent, MossCall, QueryOptions, DocumentInfo). This package is declared as a dependency in pyproject.toml (moss-agent[livekit]>=1.0.0) but does not exist anywhere in this repository, nor is it documented in AGENTS.md. The existing voice agent examples all use from moss import MossClient, QueryOptions (the standard SDK). Since moss-agent is an external dependency whose API surface cannot be verified against this repo, the correctness of method calls like agent.load_indexes(...), agent.attach(ctx), call.query_multi_index(...), and call.query(...) cannot be confirmed from the codebase alone.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Pull request overview
Adds a new self-contained LiveKit voice agent example (examples/python-moss-agent/) that showcases the external moss-agent SDK's "prewarm once, attach per room" pattern: a process-wide MossAgent loads three e-commerce indexes during worker startup, and each LiveKit room scopes a MossCall via agent.attach(ctx) for retrieval-grounded tool calls.
Changes:
- New
agent.pyusingAgentServer+setup_fncprewarm and per-roomattach(ctx), withsearch_store(multi-index) andsearch_products(single-index) tools. - New
create_indexes.pyplusdata/{product_catalog,faq,policies}.jsonfixtures to build the three indexes used by the agent. README.md,.env.example,.gitignore, andpyproject.tomlwiring the example as a uv-managed project depending onmoss-agent[livekit]>=1.0.0andlivekit-agents[...]>=1.0.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| examples/python-moss-agent/agent.py | LiveKit voice agent with process-wide MossAgent prewarm and per-room MossCall attach |
| examples/python-moss-agent/create_indexes.py | Builds the three Moss indexes from JSON fixtures |
| examples/python-moss-agent/data/product_catalog.json | Sample product docs (uses numeric price_usd metadata) |
| examples/python-moss-agent/data/faq.json | Sample FAQ documents for the FAQ index |
| examples/python-moss-agent/data/policies.json | Sample policy documents for the policies index |
| examples/python-moss-agent/README.md | Setup, walkthrough, sample conversation, file map |
| examples/python-moss-agent/pyproject.toml | Declares moss-agent and livekit-agents dependencies |
| examples/python-moss-agent/.env.example | Required env vars for Moss, OpenAI, Deepgram, Cartesia, LiveKit |
| examples/python-moss-agent/.gitignore | Excludes .env, .venv/, and Python build artifacts |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "metadata": {"category": "audio", "sku": "AUR-OE-001", "price_usd": 279} | ||
| }, | ||
| { | ||
| "id": "p-aurora-buds", | ||
| "text": "Aurora Buds true wireless earbuds. ANC plus transparency mode, 8 hours per bud (28 hours with case), IPX5 sweat resistant, wireless charging case. Half the noise cancellation of the over-ear Pro. $149. Colors: black, white.", | ||
| "metadata": {"category": "audio", "sku": "AUR-TW-002", "price_usd": 149} | ||
| }, | ||
| { | ||
| "id": "p-luma-lamp", | ||
| "text": "Luma desk lamp. Full-spectrum LED, 5 color temperatures from 2700K warm to 6500K daylight, USB-C output for charging your phone from the base. Touch-dim, no buttons. $89.", | ||
| "metadata": {"category": "home", "sku": "LUM-DSK-010", "price_usd": 89} | ||
| }, | ||
| { | ||
| "id": "p-luma-floor", | ||
| "text": "Luma floor lamp. Same full-spectrum panel as the desk lamp scaled to a 60-inch column, foot-tap controls, motion-activated dim-to-night mode. $229.", | ||
| "metadata": {"category": "home", "sku": "LUM-FLR-011", "price_usd": 229} | ||
| }, | ||
| { | ||
| "id": "p-nimbus-backpack", | ||
| "text": "Nimbus 22L commuter backpack. Padded 16-inch laptop sleeve, weatherproof recycled ripstop shell, magnetic chest strap, hidden RFID-blocking passport pocket. Carry-on legal on every major US airline. $139.", | ||
| "metadata": {"category": "bags", "sku": "NIM-BP-022", "price_usd": 139} | ||
| }, | ||
| { | ||
| "id": "p-nimbus-sling", | ||
| "text": "Nimbus crossbody sling. 4L, fits an iPad mini, water bottle pocket, anti-theft locking zipper. $69.", | ||
| "metadata": {"category": "bags", "sku": "NIM-SL-004", "price_usd": 69} | ||
| }, | ||
| { | ||
| "id": "p-tide-bottle", | ||
| "text": "Tide vacuum-insulated bottle. 24oz, keeps cold drinks cold for 36 hours and hot drinks hot for 12. Dishwasher-safe lid. $39. Colors: storm, dune, moss.", | ||
| "metadata": {"category": "drinkware", "sku": "TID-BTL-024", "price_usd": 39} | ||
| }, | ||
| { | ||
| "id": "p-tide-mug", | ||
| "text": "Tide travel mug. 16oz, leak-proof flip lid, fits standard car cup holders, double-wall vacuum insulation. $29.", | ||
| "metadata": {"category": "drinkware", "sku": "TID-MUG-016", "price_usd": 29} | ||
| }, | ||
| { | ||
| "id": "p-helix-keyboard", | ||
| "text": "Helix 75% mechanical keyboard. Hot-swap sockets, gasket-mounted PCB, lubed tactile switches, RGB underglow, Bluetooth + 2.4GHz + USB-C wired. Mac and Windows layouts both ship with every order. $199.", | ||
| "metadata": {"category": "desk", "sku": "HLX-KB-075", "price_usd": 199} | ||
| }, | ||
| { | ||
| "id": "p-helix-mouse", | ||
| "text": "Helix wireless mouse. 26K DPI optical sensor, 6 programmable buttons, 70-hour battery, 1ms latency on the 2.4GHz dongle. $89.", | ||
| "metadata": {"category": "desk", "sku": "HLX-MS-001", "price_usd": 89} |
| DocumentInfo( | ||
| id=doc["id"], | ||
| text=doc["text"], | ||
| metadata=doc.get("metadata", {}), |
An example of a support voice agent built on the
moss-agentSDK, demonstrating process-wide index prewarming and per-room agent attachment for high concurrency and low-latency knowledge base search.The most important changes are:
New Example Application: Ecommerce Support Voice Agent
agent.py, a fully documented example implementing a LiveKit-based voice support agent using themoss-agentSDK. It demonstrates process-wide index prewarming, per-room agent scoping, and multi-index retrieval for product, FAQ, and policy queries.Index Creation and Data Ingestion
create_indexes.py, a script to build the three required Moss indexes (ecommerce_products,ecommerce_faq,ecommerce_policies) from the included sample data files.data/product_catalog.json(10 products),data/faq.json(8 FAQ entries), anddata/policies.json(7 policy docs) for index creation.Documentation and Configuration
README.mdwith setup instructions, code walkthrough, sample conversations, and resource links to help users understand and run the example..env.examplelisting all required environment variables for Moss, OpenAI, Deepgram, Cartesia, and LiveKit, and updated.gitignoreto exclude secrets and local files.