Blog / Technical paper
Technical paperConnecting SI phone agents to a live load board
How SmartLoads' voice agents find the right load while a carrier is on the phone. One lookup webhook handles load numbers and spoken lanes, is scoped by agency and customer, returns only fields that are safe to say out loud, and turns each call into a lead tied to the right load.
SmartLoads' super intelligence (SI) phone agents call one webhook, lookup-load, while the carrier is talking. It accepts a load number or a spoken lane (cities, states, equipment). It cleans up what speech-to-text and the language model send, searches the agency's open loads, and returns at most five matches with only speakable fields. That means the starting rate but never the maximum pay, the customer's name or the raw rate. The dialed number or a customer slug scopes the search to one shipper's freight, and an unknown scope returns nothing rather than everything. After the call, the lead is tied to a load only when the load number resolves to exactly one open load, and repeat callers update their pending lead instead of creating another. Between May 14 and September 25, 2026, the agents answered 14,232 carrier calls.
When a carrier calls about a load and a broker can't pick up, SmartLoads' SI phone agent answers. The conversation only works if the agent can find the right load while the carrier is still talking: "the rebar out of Jewett going to Weimar", or "load 4-1-8", read off a load board with a road in the background.
This paper covers the one tool that makes that possible, a load-lookup webhook, and what happens after the call. Between May 14 and September 25, 2026, SmartLoads' agents answered 14,232 carrier calls at one agency (the business side).
The agents
The agents run on a voice AI platform (mainly Synthflow). Each agent has its own phone number and job:
- one on the DAT posting number
- two on the Truckstop posting numbers
- one on a direct line
- customer-specific agents that answer for a single shipper's freight
Every agent uses the same lookup tool.
One webhook for both kinds of question
POST /functions/v1/lookup-load takes the agency plus whatever the carrier gave:
{ "agency_id": "…", "load_number": "SL-TX-0418" }
{ "agency_id": "…", "origin_city": "Jewett", "origin_state": "TX", "destination_city": "Weimar", "equipment": "flatbed" }
There used to be a separate lane-search tool. Folding both searches into one tool with optional fields means one thing to configure on every agent, and one less choice for the model to get wrong.
Cleaning what the model sends
The inputs come from speech-to-text, then a language model filling in tool arguments. Both make predictable mistakes, so the webhook normalizes before it searches:
- Unfilled placeholders are dropped. Models sometimes send the template itself, like
<origin_city>or{destination}, when the carrier didn't say a city. Those values are treated as absent. - "City, ST" is split. "Jewett, TX" in the city field becomes a city and a state.
- State names become codes. "Texas" becomes
TX. - Load numbers ignore punctuation. Dashes and spaces are removed, and a partial number still matches, because carriers read numbers in fragments.
Searching
The search only looks at loads a carrier could actually get: active, open and not archived, for the calling agency.
- Load number: match on the normalized number.
- Lane: match pickup and destination cities by containment, trailer type if given, and the state exactly when one was said.
- Nothing exact? Offer loads from the origin or to the destination, so the agent can still say "I don't have that lane, but I have two loads out of Jewett."
It returns at most five loads, because a voice agent reading a list longer than that loses the caller.
Open loads for each agency are held in a small in-memory cache for five minutes (up to 5,000 rows), so a burst of calls after a morning posting doesn't mean a burst of database queries.
Returning only what's safe to say
The response is written for a voice, and for a caller who isn't your customer:
| Returned | Never returned |
|---|---|
| Load number, lane, pickup and delivery, ship date | Maximum pay |
| Starting rate (target pay), and whether it's per ton | Raw customer rate |
| Trailer type, truck size, length, tarp requirement | Customer name |
| Weight, miles, commodity, notes |
The agent can't reveal the maximum pay, because it never receives it. That's a stronger guarantee than instructing the model not to say it. The same thinking keeps booking out of the agent's hands entirely (why).
Scoping by customer
Some shippers get their own phone number on their load postings, answered by an agent that knows only their freight. The scope comes from either the number that was dialed (mapped to the shipper) or a customer slug in the agent's tool configuration.
An unknown scope fails closed. If the slug doesn't match a customer, the lookup returns no loads rather than the whole board. A misconfigured agent should say "I don't see that load", not read another shipper's freight to a stranger. For the same reason, demonstration loads are never returned on a customer's line.
After the call: a lead tied to the right load
When the call ends, the platform posts the conversation to SmartLoads, which creates a lead: carrier, MC number, contact, lane, equipment, the rate they asked for and a summary.
Linking the lead to a load is deliberately conservative:
- If the agent passed the load's internal ID, it's used as is.
- If it passed a load number, the lead is linked only if that number matches exactly one active load in the agency. No match, or several matches, leaves the lead unlinked for a broker to attach.
A wrong link is worse than no link, because it sends a broker to call about the wrong load and it corrupts the lead-to-load reporting.
Repeat callers don't multiply. A carrier who calls three times in an hour about the same lane is one lead, not three. If a pending lead from the same agency and phone number exists from the last 24 hours, it's updated instead of duplicated.
When a lead is tied to a load, the lead.matched_load webhook fires. That's how an agency's Slack channel gets "Lead matches a load", with the carrier's phone number, within about 30 seconds.
Lessons
- Design tools for the model you have. Expect placeholders, wrong fields and partial numbers, and normalize before you search.
- Return less. Give the agent five speakable results and only the fields it may say. Leaving a secret out of the response beats a prompt rule.
- Fail closed on scope. An empty answer is recoverable; reading the wrong shipper's loads isn't.
- Link conservatively. Link a lead to a load only on an unambiguous match.
Frequently asked questions
Which voice platform does SmartLoads use?
Mainly Synthflow, with support for ElevenLabs and a Telnyx AI assistant pilot. The lookup webhook is platform-neutral: any agent that can call an HTTPS tool with JSON can use it.
Can the SI agent tell a carrier the maximum rate?
No. The lookup never returns the maximum pay, so the agent can't say it. It quotes the starting rate and records what the carrier asks for.
What if a carrier gives a load number that's been booked?
Booked loads aren't open, so they aren't returned. The agent offers other loads on the same lane or out of the same city instead.
How does the agent know which shipper's loads to offer?
From the number the carrier dialed, or the agent's configured customer. Customer-specific numbers only ever see that customer's loads.