Small businesses still rely heavily on phone calls for procurement.
A repair shop that urgently needs a replacement part may have to stop working, call several suppliers one by one, ask the same questions about stock, price, warranty, delivery, and pickup, write the answers down manually, and then decide who to call again.
The information exists, but it is trapped inside phone conversations.
That is the problem behind SupplyScout Voice.
What it does
SupplyScout Voice turns supplier phone calls into a structured procurement workflow.
A user creates a sourcing request such as:
One alternator for a 2019 Renault Clio, budget €180, needed today.
SupplyScout then:
- retrieves bounded procurement context;
- prepares a structured supplier call brief;
- requires explicit human approval before any outbound call;
- uses CALL-E to perform the phone call;
- tracks the provider call ID and call status;
- converts the returned information into a structured supplier quote;
- preserves missing information as
Unknowninstead of inventing facts; - ranks supplier offers deterministically;
- lets the human make the final supplier decision;
- requires a second explicit approval before any reservation call.
SupplyScout never autonomously purchases or pays for anything.
CALL-E is the real phone-call runtime behind SupplyScout.
For an approved supplier, the backend sends CALL-E:
- the supplier recipient;
- a structured call task;
- the information the agent needs to collect;
- a closed result schema;
- metadata;
- an idempotency key.
SupplyScout then polls CALL-E for the result, stores the provider call ID, tracks the call lifecycle, and normalizes the returned supplier facts.
For production validation, I completed a real CALL-E call to the official US hackathon test hotline. CALL-E returned a real provider call ID and the call successfully reached completed status.
Because the hotline is not a real auto-parts supplier, it did not provide real inventory information. SupplyScout correctly preserved those values as Unknown instead of hallucinating stock, price, warranty, or delivery information.
The frontend is built with "Next.js and TypeScript".
The backend uses"FastAPI and Python" with "LangGraph"for the procurement workflow.
The agent state moves through stages such as:
request_created → context_retrieval → call_preview → awaiting_quote_approval → supplier_calls_dispatched → quotes_normalized → ranked → awaiting_human_selection → reservation_preview
Supplier and workflow data are stored in "PostgreSQL on Supabase".
For retrieval, SupplyScout uses "pgvector"with "FastEmbed"and the BAAI/bge-small-en-v1.5 embedding model.
The retrieval layer is intentionally bounded: historical or reference context can help prepare the call, but it is never treated as authority for live price, stock, or availability.
Those facts must come from the supplier call itself.
Supplier ranking is deterministic rather than LLM-generated, so the ranking can be inspected and reproduced.
The backend is deployed on "Railway" and the frontend is deployed on "Vercel".
Safety by design
Real phone calls create real-world side effects, so I designed SupplyScout with several controls:
- explicit human approval before outbound calls;
- strict recipient allowlisting;
- E.164 phone validation;
- server-side credentials;
- idempotent call attempts;
- no automatic retry after an uncertain failure;
- missing supplier facts remain unknown;
- human-controlled supplier selection;
- separate approval for reservation;
- no autonomous purchase or payment;
- fake mode for safe demonstrations and testing.
Challenges I ran into
One challenge was handling provider restrictions during live testing.
An earlier France/French test route became temporarily unavailable through CALL-E. Instead of trying to bypass the restriction, I used CALL-E's official US hackathon test hotline in English for production validation.
Another important challenge was preventing duplicate calls. A network failure after a request has already reached a phone provider can make retries dangerous. SupplyScout therefore records call attempts and uses idempotency so a failed or uncertain attempt is not blindly redialed.
I also had to separate AI reasoning from business truth. An LLM can help prepare context, but it should never invent stock, price, delivery, or warranty information. The live call is the source for those facts.
Accomplishments
I am especially proud that SupplyScout combines several layers into one controlled workflow:
- real CALL-E phone-call integration;
- human approval gates;
- structured supplier-result extraction;
- uncertainty preservation;
- semantic retrieval with pgvector;
- deterministic quote ranking;
- persistent workflow state;
- a separate reservation approval boundary;
- production deployment on Vercel, Railway, and Supabase.
The backend test suite passes more than 100 tests, and the frontend test, lint, typecheck, and production build checks pass as well.
What I learned
The hardest part of building a phone-call agent is not making the phone call.
It is deciding what the call is allowed to do, what information can be trusted, how uncertainty is represented, and when control must return to a human.
That became the central design principle of SupplyScout Voice.
What's next
The demo focuses on independent auto repair shops, but the same workflow can apply to many businesses that still obtain critical supplier information over the phone.
Future versions could support:
- additional procurement verticals;
- supplier history and reliability scoring;
- multilingual supplier workflows;
- richer supplier analytics;
- additional approved call regions;
- team workspaces and procurement dashboards.
The long-term goal is simple:
turn supplier phone conversations into structured, auditable software workflows without removing human control.
Built With
- call-e
- fastapi
- fastembed
- langchain
- langgraph
- next.js
- pgvector
- postgresql
- python
- railway
- react
- supabase
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.