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

推荐订阅源

Know Your Adversary
Know Your Adversary
小众软件
小众软件
L
LangChain Blog
月光博客
月光博客
博客园 - Franky
Microsoft Azure Blog
Microsoft Azure Blog
Y
Y Combinator Blog
有赞技术团队
有赞技术团队
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
MongoDB | Blog
MongoDB | Blog
Recorded Future
Recorded Future
V
Visual Studio Blog
TaoSecurity Blog
TaoSecurity Blog
S
Schneier on Security
C
Cybersecurity and Infrastructure Security Agency CISA
P
Privacy & Cybersecurity Law Blog
T
Threat Research - Cisco Blogs
D
DataBreaches.Net
L
LINUX DO - 热门话题
C
Check Point Blog
F
Fortinet All Blogs
Hugging Face - Blog
Hugging Face - Blog
The Hacker News
The Hacker News
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Microsoft Security Blog
Microsoft Security Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
V
V2EX
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
The GitHub Blog
The GitHub Blog
P
Proofpoint News Feed
L
Lohrmann on Cybersecurity
博客园 - 司徒正美
T
Threatpost
P
Palo Alto Networks Blog
A
About on SuperTechFans
Spread Privacy
Spread Privacy
Engineering at Meta
Engineering at Meta
N
News | PayPal Newsroom
T
Tailwind CSS Blog
The Last Watchdog
The Last Watchdog
Blog — PlanetScale
Blog — PlanetScale
A
Arctic Wolf
量子位
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
博客园 - 聂微东
Google Online Security Blog
Google Online Security Blog
Google DeepMind News
Google DeepMind News
www.infosecurity-magazine.com
www.infosecurity-magazine.com
V
Vulnerabilities – Threatpost
H
Hacker News: Front Page

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
Build a Real-Time Voice RAG Agent for Your Documentation
Rishi Raj Ja · 2026-05-14 · via DEV Community

Ever wish you could just ask someone to explain your product or API as you build, or want a way to handle technical questions in meetings without having to ping an engineer or sift through the docs on the spot? Picture being able to pull in a real-time AI agent (think of an AI teammate) to your 1-1 calls, group sessions, or ad-hoc hangouts. You can have it teach you about the product directly, field questions from folks on the team, or even make the agent available for people to schedule quick deep-dive sessions with no need to bug the lead dev or wait for timezone overlap.

This walkthrough shows how to build and plug in an AI voice agent that sits in on your calls, listens for questions, and pulls up answers from your docs in seconds. Whether you're technical or not, it’s like pairing with someone who knows where everything is and doesn’t mind repeating the basics even after hours.

We wire everything up with Vision Agents as the voice agent framework, Stream for WebRTC audio and video, OpenAI Realtime for speech in and speech out, Anam so the agent shows up as a face on the video, and Supermemory so answers come from search over your uploaded documents instead of guesswork. The code stays small and most of the behavior lives in one registered function that asks the memory store for relevant chunks and returns them to the model.

Demo

Prerequisites

You will need the following to get going with the implementation:

  • Python 3 or later
  • uv as the Python package manager

What is RAG?

Retrieval-Augmented Generation (RAG) means the language model answers using text retrieved from your own sources (documentation, wikis, tickets) in addition to its weights. A typical loop is to turn the user question into a search query, pull the top matching passages from an index, and pass those passages into the model as context so it grounds its reply in your material. That cuts hallucinations on proprietary facts and lets answers track updates to your docs without retraining the model.

Let's look at two best practices for building high-quality RAG systems in production today:

Hybrid Search

Think of hybrid search as bringing together two different search engines to get the best of both worlds: one that understands meaning (semantic search) and one that matches keywords (like a classic text search). Semantic search is great at catching the “vibe” or intent, even if someone asks for something in a totally different way. Meanwhile, keyword search is your go-to for finding specifics, like exact function names, class names, or error codes.

By letting both approaches take a shot and then combining their results (using methods like reciprocal rank fusion), you dodge the common failure modes of each. Doing this means you’re much less likely to miss the chunk of doc you really wanted, even if your question is a little funky.

Re-ranking

Re-ranking is basically a quality filter for search results. First, you cast a wide net and pull back a bunch of potentially relevant chunks, ensuring that you are not missing anything useful. Then, a smarter model (cross-encoder or dedicated reranker) takes a closer look, comparing your question directly to each chunk, and shuffles the list to put the best matches at the top.

This two-step approach pays off in the sense that you get all the coverage of a broad search but with the accuracy of a model that actually “reads” for context. In practice, this means you get better, more grounded answers from your search compared to just using a simple top-k retrieval.

In the Supermemory example below, using rerank=True in the document search API enables this second-stage refinement i.e. the platform reranks the initially retrieved results, so only the best chunks are provided to the model.

Setting Up Environment Variables

To configure your application, set up the necessary environment variables for each integration. Follow the steps below for each provider:

Create a Stream application

  • Go to the Stream dashboard.
  • Choose + Create an App.
  • In the dialog, type a name for your application and pick the region for your edge-server location(s).
  • After creation, locate the API Key and Secret under Your Credentials.

Stream Application Overview

  • Add these credentials to your .env file as follows:
   STREAM_API_KEY="your-api-key"
   STREAM_API_SECRET="your-api-secret"

Enter fullscreen mode Exit fullscreen mode

Configure OpenAI

   OPENAI_API_KEY="your-openai-api-key"

Enter fullscreen mode Exit fullscreen mode

Ensure your organization can use the Realtime API and the model you pick in code (here, gpt-realtime-1.5).

Configure Anam

   ANAM_API_KEY="your-anam-api-key"

Enter fullscreen mode Exit fullscreen mode

  • Open Anam Build.
  • Click Avatar, hover the avatar you want, and click Copy ID.

Anam Avatar ID

  • Add the ID to your .env file:
   ANAM_AVATAR_ID="your-anam-avatar-id"

Enter fullscreen mode Exit fullscreen mode

Configure Supermemory

   SUPERMEMORY_API_KEY="your-supermemory-api-key"

Enter fullscreen mode Exit fullscreen mode

That's it for configuring your environment variables. Next, let's move on to scripting the AI voice agent.

Set up a new Python application

In this section, you will learn how to create a new Python application, set up vision agents in it, and install relevant libraries for a quick implementation.

Let’s get started by creating a new Python project. Open your terminal and run the following commands:

mkdir voice-agent && cd voice-agent
uv init && uv add "vision-agents[anam,getstream,openai,redis]" python-dotenv supermemory ultimate-sitemap-parser

Enter fullscreen mode Exit fullscreen mode

Now, create a .env file at the root of your project. You are going to add the items we saved from the above sections.

It should look something like this:

# .env

## Stream
STREAM_API_KEY="..."
STREAM_API_SECRET="..."

## OpenAI (Realtime)
OPENAI_API_KEY="sk-proj-..."

## Anam
ANAM_API_KEY="..."
ANAM_AVATAR_ID="...-...-...-...-..."

## Supermemory
SUPERMEMORY_API_KEY="..."

Enter fullscreen mode Exit fullscreen mode

Then add main.py with a minimal agent - Stream for WebRTC and OpenAI Realtime for speech:

from dotenv import load_dotenv
from vision_agents.core import Agent, AgentLauncher, Runner
from vision_agents.core.edge.types import User
from vision_agents.plugins import getstream, openai

load_dotenv()

async def create_agent(**kwargs) -> Agent:
    agent = Agent(
        edge=getstream.Edge(),  # GetStream edge network for AV transport
        agent_user=User(name="Docs AI", id="agent"),  # Agent's identity
        instructions=("You are a helpful assistant on this call."),
        llm=openai.Realtime(model="gpt-realtime-1.5", voice="ash"),
    )
    return agent

async def join_call(agent: Agent, call_type: str, call_id: str, **kwargs) -> None:
    call = await agent.create_call(call_type, call_id)
    # Context manager handles join and clean-up automatically
    async with agent.join(call):
        await agent.finish()

if __name__ == "__main__":
    # Entrypoint for CLI: launches agent and runs the join_call automatically when invoked from the command line
    Runner(AgentLauncher(create_agent=create_agent, join_call=join_call)).cli()

Enter fullscreen mode Exit fullscreen mode

The code block above loads the environment variables, then create_agent returns an Agent that connects to Stream using getstream.Edge() and converses in real-time using openai.Realtime with a chosen model and voice. The Docs AI name is what people see in the call. join_call method creates the call, joins it, and exits cleanly when the call finishes.

Bring Your Voice Agent to Life with an Anam Avatar

Anam adds a real time interactive avatar to the agent. The avatar speaks with natural movements and automatic lip sync, which makes a voice agent feel like a present participant on a video call instead of an invisible bot.

Vision Agents ships an Anam integration as a processor. A processor in this context is a flexible building block i.e. it can be an avatar like Anam, a computer vision model (like YOLO), or any custom Python code designed to intercept raw WebRTC audio and video streams, perform some manipulation or transformation, and then republish the processed result back into the Stream call. For Anam, the processor takes audio output from the agent, streams it to the Anam service, and then publishes the resulting animated avatar video and audio as part of the group call experience.

Make the following changes to add Anam avatar to your agent:

# existing imports

+ from vision_agents.plugins.anam import AnamAvatarPublisher

async def create_agent(**kwargs) -> Agent:
    ...
    agent = Agent(
        ...
+        processors=[AnamAvatarPublisher()],
    )

    return agent

# rest of the file

Enter fullscreen mode Exit fullscreen mode

The code block above integrates Anam avatars into your agent by importing AnamAvatarPublisher and adding it to the agent's processors list, enabling the agent to produce a real-time animated avatar with expressions in calls.

Index your documentation

Supermemory is the memory layer for AI agents, a context-engineering platform that exposes APIs for adding knowledge and retrieving it later.

When you add documents, you send raw content (plain text, URLs, uploads, and more) and then Supermemory runs a processing pipeline that validates and stores the request, extracts text when needed (scraping for URLs), chunks that material into searchable pieces, embeds those chunks for vector search, and indexes them for retrieval.

Create a sitemap.py file with the code below to automatically crawl and index your website's public docs pages into Supermemory for retrieval by your Docs AI agent:

from dotenv import load_dotenv
from supermemory import Supermemory
from usp.tree import sitemap_tree_for_homepage

load_dotenv()

supermemory_client = Supermemory()

def add_sitemap_to_memory(url: str) -> list[str]:
    tree = sitemap_tree_for_homepage(url)
    for link in enumerate(tree.all_pages()):
        supermemory_client.documents.add(content=link.url)

if __name__ == "__main__":
    add_sitemap_to_memory("https://your-website-url.com/")

Enter fullscreen mode Exit fullscreen mode

Then, run the indexing script via the following command in your terminal:

uv run sitemap.py

Enter fullscreen mode Exit fullscreen mode

Finally, wait until indexing finishes for those documents in the Supermemory console before relying on search in the voice agent.

Ask your documentation

The voice agent in your calls needs a way to search the documents you have indexed in Supermemory. In the agentic world, one of the ways to achieve this is via function calling. Function calling is when the model can call a tool you define instead of only replying in plain text. Your code runs, returns a result, and the model uses that result in what it says next. That function can be anything you would run in normal app code i.e. HTTP calls, database queries, or in our case supermemory_client.search.documents to pull ranked chunks from the index you built earlier.

Vision Agents wires this up with a decorator on your LLM as @agent.llm.register_function() which exposes an async Python function to the model, with a short description so it knows when and how to use it. The framework handles registration and the call loop while having you focus on creating the function body.

Now, make the following changes to add the function call for searching the documents:

# existing imports

+ from supermemory import Supermemory

async def create_agent(**kwargs) -> Agent:
+     supermemory_client = Supermemory()
      agent = Agent(
          ...
          instructions=(
-             "You are a helpful assistant on this call."
+             """You are a helpful document Q&A assistant. When asked a question, use the ask_docs function.
+
+ INSTRUCTIONS:
+ 1. Answer the question using ONLY the information from the provided response.
+ 2. If the response doesn't contain enough information, say so clearly
+ 3. Be accurate and quote directly when possible
+ 4. Maintain a helpful, professional tone
+ 5. If you do not know the answer, say so clearly
+ """
          ),
      )
+     @agent.llm.register_function(
+         description="Ask a question in natural language about the documentation"
+     )
+     async def ask_docs(question: str) -> str:
+         """Ask a question in natural language about the documentation"""
+         search_results = supermemory_client.search.documents(
+             q=question, rerank=True, include_full_docs=False, include_summary=True
+         )
+         if not search_results.results:
+             return "I couldn't find any relevant information in the uploaded documents to answer your question."
+         context_parts = []
+         for index, result in enumerate(search_results.results):
+             relevant_chunks = [
+                 chunk.content for chunk in result.chunks if chunk.is_relevant
+             ][:3]
+             chunk_text = "\n\n".join(relevant_chunks)
+             context_parts.append(
+                 f'[Document {index + 1}: "{result.title}"]\n{chunk_text}'
+             )
+         return "\n\n---\n\n".join(context_parts)
      return agent

# rest of the file

Enter fullscreen mode Exit fullscreen mode

The code block above imports the Supermemory client, initializes it, and passes it into the agent. The instructions for the agent are detailed so as to ensure the model only uses retrieved document context, is accurate, and admits any knowledge gap. The ask_docs function is registered as a callable tool for the model i.e. when the agent receives a question, it queries Supermemory for relevant documents, extracts and joins their most relevant chunks, and structures the output with document titles for clear answers. If no relevant results are found, it lets the user know. This enables the model to reliably and transparently answer questions using only information from your uploaded documentation.

How to Run

To launch the service locally, use the following command in your terminal:

uv run main.py run

Enter fullscreen mode Exit fullscreen mode

It will open a demo at demo.visionagents.ai and automatically join the session for you. You can then interact with your teammate in real time, as demonstrated in the demo.

The terminal will display the following output prior to the agent joining the call, confirming that the ask_docs tool has been automatically registered:

% uv run main.py run

14:16:18.214 | INFO     | 🚀 Launching agent...
...
14:16:19.101 | INFO     | [Agent: agent] | 🤖 Agent joining call: 27d3df64-8df7-404f-be3a-2c25374a521b
+ 14:16:19.101 | INFO     | Added 1 tools to session config: ['ask_docs']
14:16:19.733 | INFO     | 🌐 Opening browser to: https://demo.visionagents.ai/join/...
...

Enter fullscreen mode Exit fullscreen mode

Ending thoughts

You now have a voice participant that can sit in on a call, pull answers from your indexed docs, and speak them back with a face on the video. This is especially valuable for teammates who aren't deep in the codebase or may not be available due to timezone differences. It's exciting to see how agents like this are evolving to meet real-world use cases, and how frameworks such as Vision Agents make it straightforward to build and integrate these capabilities into your workflows.