Skip to content

feat(vapi-moss): VAPI Custom Tool integration for Moss#113

Merged
ashvathsureshkumar merged 5 commits intomainfrom
feat/vapi-moss
Apr 8, 2026
Merged

feat(vapi-moss): VAPI Custom Tool integration for Moss#113
ashvathsureshkumar merged 5 commits intomainfrom
feat/vapi-moss

Conversation

@ashvathsureshkumar
Copy link
Copy Markdown
Contributor

@ashvathsureshkumar ashvathsureshkumar commented Apr 3, 2026

Summary

  • New packages/vapi-moss package with MossVapiSearch class for framework-agnostic Moss search + HMAC signature verification
  • New apps/vapi-moss demo app — FastAPI server handling VAPI Custom Tool webhooks with preloaded index for sub-10ms retrieval
  • Follows existing monorepo patterns (elevenlabs-moss, pipecat-moss)

Architecture

User speaks → VAPI STT → LLM refines query → tool-calls request → FastAPI server → Moss query → Results returned → LLM synthesizes → TTS

Open with Devin

…earch

New package (`packages/vapi-moss`) and demo app (`apps/vapi-moss`) that
connect VAPI voice agents to Moss via a Custom Tool webhook. The LLM
decides when to search and refines the query, delivering sub-10ms
retrieval from a preloaded Moss index.

- `MossVapiSearch` class with `load_index()` + `search()` for clean separation
- HMAC-SHA256 webhook signature verification on raw bytes
- FastAPI server with lifespan index preload and fail-closed startup
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new vapi-moss Python package and a companion FastAPI demo app to integrate Moss semantic search with VAPI Custom Tool / Knowledge Base webhooks, including optional HMAC signature verification.

Changes:

  • Introduces packages/vapi-moss with MossVapiSearch (preloaded index + VAPI-shaped results) and verify_vapi_signature (HMAC-SHA256).
  • Adds apps/vapi-moss demo FastAPI server that preloads an index at startup and serves /tool/search webhook requests.
  • Provides documentation, example env file, and an index creation helper script.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/vapi-moss/src/vapi_moss/signature.py Implements webhook signature verification helper
packages/vapi-moss/src/vapi_moss/search.py Implements MossVapiSearch adapter and VAPI result formatting
packages/vapi-moss/src/vapi_moss/init.py Exposes public package API / re-exports
packages/vapi-moss/README.md Package usage and signature verification docs
packages/vapi-moss/pyproject.toml Packaging + dependencies + ruff configuration
packages/vapi-moss/LICENSE Adds package license file
apps/vapi-moss/server.py FastAPI webhook server for VAPI tool calls using Moss
apps/vapi-moss/README.md Demo app setup and VAPI assistant configuration instructions
apps/vapi-moss/pyproject.toml Demo app dependencies and local workspace wiring
apps/vapi-moss/env.example Example environment configuration
apps/vapi-moss/create_index.py Utility script to create a demo Moss index with sample docs

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +34 to +37
expected = "sha256=" + hmac.new(
secret.encode(), raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

verify_vapi_signature does an exact string compare against the full header value. This will reject otherwise-valid signatures if the provider varies formatting (e.g., leading/trailing whitespace, uppercase hex digest, or SHA256= prefix). Consider normalizing/parsing the header (strip whitespace, case-insensitive sha256= handling) and comparing only the hex digest (lowercased) with hmac.compare_digest.

Suggested change
expected = "sha256=" + hmac.new(
secret.encode(), raw_body, hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature_header)
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
normalized_header = signature_header.strip()
if "=" in normalized_header:
algorithm, _, provided = normalized_header.partition("=")
if algorithm.strip().lower() != "sha256":
return False
else:
provided = normalized_header
provided = provided.strip().lower()
return hmac.compare_digest(expected, provided)

Copilot uses AI. Check for mistakes.
Comment thread apps/vapi-moss/server.py Outdated
MOSS_PROJECT_ID = os.getenv("MOSS_PROJECT_ID")
MOSS_PROJECT_KEY = os.getenv("MOSS_PROJECT_KEY")
INDEX_NAME = os.getenv("MOSS_INDEX_NAME", "product-knowledge")
WEBHOOK_SECRET = os.getenv("VAPI_WEBHOOK_SECRET", "")
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WEBHOOK_SECRET is read directly from the environment and used as the HMAC key. If the secret is set via .env/CI with trailing whitespace or a newline, signature verification will fail. Consider stripping whitespace when reading the env var (and likewise strip the incoming header value before verification).

Suggested change
WEBHOOK_SECRET = os.getenv("VAPI_WEBHOOK_SECRET", "")
WEBHOOK_SECRET = os.getenv("VAPI_WEBHOOK_SECRET", "").strip()

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

…hitespace

Address Copilot review feedback:
- Parse signature header case-insensitively and strip whitespace
- Strip trailing whitespace/newlines from WEBHOOK_SECRET env var
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 3, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
next-js Ready Ready Preview, Comment Apr 3, 2026 5:27am

Request Review

Comment thread apps/vapi-moss/create_index.py Outdated
Comment thread packages/vapi-moss/src/vapi_moss/search.py Outdated
Comment thread apps/next-js/next.config.ts Outdated
- Replace inferedge-moss with moss>=1.0.0 across package and app
- Remove create_index.py demo script — users provide their own index
- Make MOSS_INDEX_NAME required (no default)
- Regenerate uv.lock
devin-ai-integration[bot]

This comment was marked as resolved.

VAPI sends tool call parameters under function.arguments, not
parameters. Handle both formats and string-encoded JSON arguments.
devin-ai-integration[bot]

This comment was marked as resolved.

- Handle malformed JSON in tool call arguments gracefully
- Add pytest to dev dependencies
- Add tests for signature verification and search formatting
@ashvathsureshkumar ashvathsureshkumar merged commit 0d9d14c into main Apr 8, 2026
19 checks passed
Atulsingh1155 pushed a commit to Atulsingh1155/moss that referenced this pull request Apr 30, 2026
## Summary
- New `packages/vapi-moss` package with `MossVapiSearch` class for
framework-agnostic Moss search + HMAC signature verification
- New `apps/vapi-moss` demo app — FastAPI server handling VAPI Custom
Tool webhooks with preloaded index for sub-10ms retrieval
- Follows existing monorepo patterns (`elevenlabs-moss`, `pipecat-moss`)

## Architecture
```
User speaks → VAPI STT → LLM refines query → tool-calls request → FastAPI server → Moss query → Results returned → LLM synthesizes → TTS
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants