Skip to content

feat(tools): add phone_call tool for outbound AI voice calls#847

Closed
mormio wants to merge 1 commit into
mainfrom
feat/phone-call-tool
Closed

feat(tools): add phone_call tool for outbound AI voice calls#847
mormio wants to merge 1 commit into
mainfrom
feat/phone-call-tool

Conversation

@mormio

@mormio mormio commented Mar 10, 2026

Copy link
Copy Markdown
## What does this PR do?

Add `phone_call` and `phone_call_result` tools for making outbound
phone calls via AI voice agents. Enables the agent to schedule
appointments, make reservations, and deliver messages by phone on
the user's behalf.

Two providers supported (user chooses during first-time setup):

- **Bland.ai** (default): all-in-one, one API key, built-in voices
- **Vapi**: flexible platform — plug in any voice provider
  (ElevenLabs, Deepgram, PlayHT) and telephony (Twilio, Vonage,
  Telnyx). Better voice quality, more setup.

Provider selected via config.yaml or env vars. Tools only appear
when at least one provider is configured (check_fn gates them).

## Related Issue

No existing issue — this is a new capability.

## Type of Change

- [x] ✨ New feature (non-breaking change that adds functionality)

## Changes Made

- `tools/phone_tool.py`: new tool module — `phone_call` (initiate
  outbound call) and `phone_call_result` (poll for transcript/status)
- `toolsets.py`: add "phone" toolset definition + add both tools
  to `_HERMES_CORE_TOOLS`
- `model_tools.py`: add `tools.phone_tool` to `_discover_tools()` list

## How to Test

**Bland.ai (quick):**
1. Sign up at https://app.bland.ai (free, ~$2 trial credit)
2. Set `BLAND_API_KEY` env var
3. Run: `hermes -q "Call +15551234567 and ask what time they close"`
4. Agent should confirm before dialing, make the call, then report transcript

**Vapi (better voice quality):**
1. Sign up at https://dashboard.vapi.ai + https://twilio.com
2. Buy a Twilio number, import into Vapi
3. Set `VAPI_API_KEY` and `VAPI_PHONE_NUMBER_ID`
4. Set `phone.provider: vapi` in config.yaml
5. Same test as above

**Without any provider configured:**
- Tools should not appear in the agent's tool list (check_fn returns False)

## Checklist

### Code
- [x] I've read the Contributing Guide
- [x] My commit messages follow Conventional Commits
- [x] I searched for existing PRs to make sure this isn't a duplicate
- [x] My PR contains only changes related to this feature
- [x] I've run `pytest tests/ -q` and all tests pass
      (same 8 pre-existing collection errors on main and this branch)
- [ ] I've added tests for my changes — not yet, would appreciate
      guidance on mocking external API calls in the test suite
- [x] I've tested on my platform: Ubuntu (Linux)

### Documentation & Housekeeping
- [ ] I've updated relevant documentation — N/A (tool is
      self-documenting via schema descriptions)
- [ ] I've updated cli-config.yaml.example — should add phone
      section, happy to do in a follow-up
- [ ] I've updated CONTRIBUTING.md or AGENTS.md — N/A
- [x] I've considered cross-platform impact — uses only `requests`
      library, no OS-specific code
- [x] I've updated tool descriptions/schemas

## Screenshots / Logs

Tested with real calls via both providers:

Bland.ai call

phone_call(<phone_number_hidden>, "Deliver a message from Morgane")
→ call_id: b1c18c55-...
→ Transcript: AI delivered message, user responded

Vapi + ElevenLabs + Twilio call

phone_call(<phone_number_hidden>, "Test voice quality")
→ call_id: 019cd87a-...
→ Transcript: User confirmed voice quality improvement

Add phone_call and phone_call_result tools for making outbound phone
calls via AI voice agents. Supports two providers:

- Bland.ai (default): simple all-in-one, one API key, built-in voices
- Vapi: flexible platform with ElevenLabs/Deepgram/PlayHT voices and
  Twilio/Vonage/Telnyx telephony. Better voice quality, more setup.

The tool handles the API plumbing (initiating calls, polling for
transcripts/recordings). Provider is selected via config.yaml or
env vars (BLAND_API_KEY or VAPI_API_KEY + VAPI_PHONE_NUMBER_ID).

Tools only appear when at least one provider is configured
(check_fn returns False otherwise).

Files changed:
- tools/phone_tool.py: new tool module (phone_call, phone_call_result)
- toolsets.py: add 'phone' toolset + tools to _HERMES_CORE_TOOLS
- model_tools.py: add tools.phone_tool to discovery list
@mormio mormio force-pushed the feat/phone-call-tool branch from 48ea4bb to 1cbadb7 Compare March 11, 2026 14:26
@teknium1

Copy link
Copy Markdown
Contributor

Hey @mormio — thanks for this, the implementation is clean and well-structured! However, we think this would be a better fit as a skill rather than a core tool.

Phone calling is a powerful but niche capability — most users won't have Bland.ai or Vapi configured, and keeping it in the core codebase adds weight to every platform's tool list (even if gated by check_fn). As a skill, users who want it can install it on demand, and it keeps the core lean.

Skills live in ~/.hermes/skills/ and get injected as instructions when loaded via /skill or auto-matched. You can look at existing skills in the repo under skills/ for the format — they're markdown files with YAML frontmatter. The skill can include the setup instructions (API keys, config), usage examples, and the task/voice prompt templates.

Would you be open to reformulating this as a skill? Happy to help with the format if you have questions.

@teknium1 teknium1 closed this Mar 11, 2026
mormio pushed a commit that referenced this pull request Mar 11, 2026
Reformulated from core tool (PR #847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)
teknium1 pushed a commit that referenced this pull request Mar 14, 2026
Reformulated from core tool (PR #847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)
teknium1 added a commit that referenced this pull request Mar 14, 2026
…alls (#1289)

* feat: improve context compaction handoff summaries

Adapt PR #916 onto current main by replacing the old context summary marker
with a clearer handoff wrapper, updating the summarization prompt for
resume-oriented summaries, and preserving the current call_llm-based
compression path.

* fix: clearer error when docker backend is unavailable

* fix: preserve docker discovery in backend preflight

Follow up on salvaged PR #940 by reusing find_docker() during the new
availability check so non-PATH Docker Desktop installs still work. Add
a regression test covering the resolved executable path.

* test: make gateway async tests xdist-safe

Replace sync test usage of asyncio.get_event_loop().run_until_complete()
with asyncio.run() so tests do not depend on an ambient current event loop.
Also create the email disconnect poll task inside a running loop. This fixes
xdist/CI failures where workers have no current loop in MainThread.

* feat(skills): add phone-calls skill for outbound AI voice calls

Reformulated from core tool (PR #847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)

* feat(skills): expand phone-calls into optional telephony skill

Follow up on salvaged PR #965 by moving the capability into optional-skills
and broadening it from outbound AI calling to a full telephony skill. Add
Twilio number provisioning, env/state persistence, SMS/MMS, inbound SMS
polling, Vapi import helpers, and a provider decision tree while keeping
telephony out of core runtime code.

* docs(skills): clarify Hermes TTS telephony workflow

---------

Co-authored-by: aydnOktay <xaydinoktay@gmail.com>
Co-authored-by: mormio <morganemoss@gmai.com>
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 27, 2026
…alls (NousResearch#1289)

* feat: improve context compaction handoff summaries

Adapt PR NousResearch#916 onto current main by replacing the old context summary marker
with a clearer handoff wrapper, updating the summarization prompt for
resume-oriented summaries, and preserving the current call_llm-based
compression path.

* fix: clearer error when docker backend is unavailable

* fix: preserve docker discovery in backend preflight

Follow up on salvaged PR NousResearch#940 by reusing find_docker() during the new
availability check so non-PATH Docker Desktop installs still work. Add
a regression test covering the resolved executable path.

* test: make gateway async tests xdist-safe

Replace sync test usage of asyncio.get_event_loop().run_until_complete()
with asyncio.run() so tests do not depend on an ambient current event loop.
Also create the email disconnect poll task inside a running loop. This fixes
xdist/CI failures where workers have no current loop in MainThread.

* feat(skills): add phone-calls skill for outbound AI voice calls

Reformulated from core tool (PR NousResearch#847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)

* feat(skills): expand phone-calls into optional telephony skill

Follow up on salvaged PR NousResearch#965 by moving the capability into optional-skills
and broadening it from outbound AI calling to a full telephony skill. Add
Twilio number provisioning, env/state persistence, SMS/MMS, inbound SMS
polling, Vapi import helpers, and a provider decision tree while keeping
telephony out of core runtime code.

* docs(skills): clarify Hermes TTS telephony workflow

---------

Co-authored-by: aydnOktay <xaydinoktay@gmail.com>
Co-authored-by: mormio <morganemoss@gmai.com>
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 28, 2026
Reformulated from core tool (PR NousResearch#847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)
angelburgosrosado pushed a commit to angelburgosrosado/hermes-agent that referenced this pull request Apr 28, 2026
Reformulated from core tool (PR NousResearch#847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)
02356abc pushed a commit to 02356abc/hermes-agent that referenced this pull request May 14, 2026
…alls (NousResearch#1289)

* feat: improve context compaction handoff summaries

Adapt PR NousResearch#916 onto current main by replacing the old context summary marker
with a clearer handoff wrapper, updating the summarization prompt for
resume-oriented summaries, and preserving the current call_llm-based
compression path.

* fix: clearer error when docker backend is unavailable

* fix: preserve docker discovery in backend preflight

Follow up on salvaged PR NousResearch#940 by reusing find_docker() during the new
availability check so non-PATH Docker Desktop installs still work. Add
a regression test covering the resolved executable path.

* test: make gateway async tests xdist-safe

Replace sync test usage of asyncio.get_event_loop().run_until_complete()
with asyncio.run() so tests do not depend on an ambient current event loop.
Also create the email disconnect poll task inside a running loop. This fixes
xdist/CI failures where workers have no current loop in MainThread.

* feat(skills): add phone-calls skill for outbound AI voice calls

Reformulated from core tool (PR NousResearch#847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)

* feat(skills): expand phone-calls into optional telephony skill

Follow up on salvaged PR NousResearch#965 by moving the capability into optional-skills
and broadening it from outbound AI calling to a full telephony skill. Add
Twilio number provisioning, env/state persistence, SMS/MMS, inbound SMS
polling, Vapi import helpers, and a provider decision tree while keeping
telephony out of core runtime code.

* docs(skills): clarify Hermes TTS telephony workflow

---------

Co-authored-by: aydnOktay <xaydinoktay@gmail.com>
Co-authored-by: mormio <morganemoss@gmai.com>
olympus-terminal pushed a commit to olympus-terminal/hermes-agent that referenced this pull request May 16, 2026
…alls (NousResearch#1289)

* feat: improve context compaction handoff summaries

Adapt PR NousResearch#916 onto current main by replacing the old context summary marker
with a clearer handoff wrapper, updating the summarization prompt for
resume-oriented summaries, and preserving the current call_llm-based
compression path.

* fix: clearer error when docker backend is unavailable

* fix: preserve docker discovery in backend preflight

Follow up on salvaged PR NousResearch#940 by reusing find_docker() during the new
availability check so non-PATH Docker Desktop installs still work. Add
a regression test covering the resolved executable path.

* test: make gateway async tests xdist-safe

Replace sync test usage of asyncio.get_event_loop().run_until_complete()
with asyncio.run() so tests do not depend on an ambient current event loop.
Also create the email disconnect poll task inside a running loop. This fixes
xdist/CI failures where workers have no current loop in MainThread.

* feat(skills): add phone-calls skill for outbound AI voice calls

Reformulated from core tool (PR NousResearch#847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)

* feat(skills): expand phone-calls into optional telephony skill

Follow up on salvaged PR NousResearch#965 by moving the capability into optional-skills
and broadening it from outbound AI calling to a full telephony skill. Add
Twilio number provisioning, env/state persistence, SMS/MMS, inbound SMS
polling, Vapi import helpers, and a provider decision tree while keeping
telephony out of core runtime code.

* docs(skills): clarify Hermes TTS telephony workflow

---------

Co-authored-by: aydnOktay <xaydinoktay@gmail.com>
Co-authored-by: mormio <morganemoss@gmai.com>
CumulusService pushed a commit to Cumulus-Service-GmbH/hermes-agent that referenced this pull request May 30, 2026
Reformulated from core tool (PR NousResearch#847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)
CumulusService pushed a commit to Cumulus-Service-GmbH/hermes-agent that referenced this pull request May 30, 2026
Reformulated from core tool (PR NousResearch#847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)
Egavasyug pushed a commit to Egavasyug/hermes-agent that referenced this pull request Jun 10, 2026
…alls (NousResearch#1289)

* feat: improve context compaction handoff summaries

Adapt PR NousResearch#916 onto current main by replacing the old context summary marker
with a clearer handoff wrapper, updating the summarization prompt for
resume-oriented summaries, and preserving the current call_llm-based
compression path.

* fix: clearer error when docker backend is unavailable

* fix: preserve docker discovery in backend preflight

Follow up on salvaged PR NousResearch#940 by reusing find_docker() during the new
availability check so non-PATH Docker Desktop installs still work. Add
a regression test covering the resolved executable path.

* test: make gateway async tests xdist-safe

Replace sync test usage of asyncio.get_event_loop().run_until_complete()
with asyncio.run() so tests do not depend on an ambient current event loop.
Also create the email disconnect poll task inside a running loop. This fixes
xdist/CI failures where workers have no current loop in MainThread.

* feat(skills): add phone-calls skill for outbound AI voice calls

Reformulated from core tool (PR NousResearch#847 feedback) into a skill with a
standalone helper script. No new dependencies — uses only Python stdlib.

Two providers supported:
- Bland.ai (default): simple setup, one API key
- Vapi: flexible, better voice quality via ElevenLabs/Deepgram + Twilio

Includes:
- SKILL.md with full procedure, safety rules, provider docs, pitfalls
- scripts/phone_call.py CLI helper (call, status, diagnose commands)

* feat(skills): expand phone-calls into optional telephony skill

Follow up on salvaged PR NousResearch#965 by moving the capability into optional-skills
and broadening it from outbound AI calling to a full telephony skill. Add
Twilio number provisioning, env/state persistence, SMS/MMS, inbound SMS
polling, Vapi import helpers, and a provider decision tree while keeping
telephony out of core runtime code.

* docs(skills): clarify Hermes TTS telephony workflow

---------

Co-authored-by: aydnOktay <xaydinoktay@gmail.com>
Co-authored-by: mormio <morganemoss@gmai.com>
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.

2 participants