Building Forward — an SMS bot over Procore using Claude's tool use
A phone number commercial-construction field crews text to pull RFIs, drawings, submittals, and code calcs out of Procore + Autodesk Construction Cloud + OneDrive. 70 tools, a project disambiguation resolver, and the LLM-over-API failure modes that took a month to work around.
The single most-quoted line I’ve heard from commercial construction PMs is some version of:
“My field doesn’t have Procore access, so I’m the human lookup. Every text is me opening Procore on their behalf and texting back the answer.”
On a project with 4-12 active jobs, the typical PM’s day is 40-80 inbound texts of pure lookup questions. Each is 60-90 seconds of opening Procore, finding the thing, screenshotting or typing back the answer. Across a 6-PM organization that’s 30-50 hours of senior labor per week answering questions that already have answers in the project.
The default response — “just give the field Procore accounts” — fails in practice for three reasons every PM names:
- Cost. Adding 30 tradespeople adds budget for licenses that get used twice in six months.
- Adoption. Tradespeople don’t open project-management apps. They text a foreman. Every other field-tech tool of the past decade has hit this wall.
- Permission complexity. Even read-only access across 40 hires-and-quits a year burns a half-FTE on access management.
So we built Forward. A phone number the field texts. Forward reads from Procore, Autodesk Construction Cloud, and OneDrive (or SharePoint), and replies with cited answers in 2-4 seconds. No app, no login, no training. The interface is the texting thread tradespeople already use.
The architecture in one paragraph
Inbound SMS / iMessage hits a SendBlue webhook. FastAPI verifies the signature, resolves the tenant by the destination phone number, runs a field-user OTP check on first contact, and enqueues the message into a Redis-backed RQ queue. A worker pulls the message, constructs a Claude Sonnet 4.6 conversation with a system prompt + 70 tool definitions + the message history for that thread, and calls Anthropic’s tool-use loop. Each tool call hits Procore / Autodesk / OneDrive through a thin integration layer that handles OAuth, retries, and the idiosyncrasies of each API. Once Claude returns a final assistant message, the worker fires SendBlue outbound. Everything is audited; every write is queued for PM approval.
The tool catalog
70 named tools, all prompt-cached. The list covers the questions that account for the majority of field-foreman traffic:
- Drawings. Sheet pulls by number, latest revision, sheet log by date, discipline filters.
- RFIs / submittals / change orders. Search by spec section, keyword, sheet, sub, status, or dollar threshold. Live reads — no local copy of the project data.
- Specs. Section retrieval by CSI division and full-text search inside the cited section.
- Daily logs, observations, punch items, inspections, test reports. Same retrieval shape across all of them.
- Schedule. Activity lookup with predecessor / successor / slack / critical-path membership.
- Subs + pay apps. List subs by trade; pull the most recent pay application with gross / retainage / net.
- Drafts. RFI drafts, observation drafts, punch drafts, daily-log entries, inspection requests, delivery- window requests. These don’t write to Procore directly — they land in the dashboard’s approval queue where a PM clicks approve, edit, or reject.
- Code-anchored calcs. NEC wire size, voltage drop, transformer kVA, generator sizing, panel demand load, HVAC load, duct sizing, ASHRAE 62.1 ventilation, pipe size for GPM, IPC drain-pipe sizing, beam deflection, bolt allowable shear, ramp slope ADA check, OSHA fall-protection threshold, IBC stair rise/run, plus quick-takeoff math (concrete yards, drywall sheets, paint gallons, rebar LF, tile count, CMU block count).
- Photo identification. Inbound MMS photos route into Claude’s vision; the bot names what it sees (panelboard, valve, sprinkler head, etc.) and ties it back to the submittal log when it matches.
The free web versions of three calculators are live at /tools/nec-wire-size, /tools/voltage-drop, and /tools/hvac-load. Same logic the bot runs.
Project disambiguation
The interesting bit, in terms of LLM engineering, is the project-disambiguation resolver. A foreman asks “send me a-301”. That sheet number exists on every project the tenant is running. Which project does the foreman mean?
Naive approach: ask Claude to guess from context. This goes wrong fast. The foreman’s phone has been seen on 3 projects in the last month; Claude picks the most recent; actually they’re on a different job today; the foreman gets a sheet from the wrong job and doesn’t notice because A-301 looks similar; the wrong wall section gets framed.
Forward instead resolves project context BEFORE Claude sees the tool call. There’s a deterministic resolver that:
- Tracks the foreman’s “active project” per conversation thread.
- On ambiguity (no active project, or last project was >48 h ago), surfaces a one-time clarification — “Which project? Reply 1 for Tower-B, 2 for Bay-Shore, 3 for Lincoln-2.” The reply pins the active project for the thread.
- Falls through to Claude only after a project is locked. Every tool call passes the locked
project_idas a dependency-injected parameter.
This is a small thing that prevents a large class of dangerous Claude failures. The system prompt also includes the explicit instruction: “Never guess which project the user is on when the resolver hasn’t locked one. Ask.”
What broke and why
A few of the failure modes that took the most time to fix:
- Tool name drift. Adding new tools while old ones are mid-flight caused Claude to occasionally call a deprecated tool name. Fix: every push to main now runs a parity check (
TOOL_HANDLERS↔TOOL_DEFINITIONS) in CI. Mismatches fail the build. - Procore rate-limiting. A single foreman asking “what change orders are open” can fan out to 4-6 Procore API calls. With multiple foremen on the same tenant, we’d hit 429s. Fix: per-tenant token-bucket rate-limiter against Procore at the integration layer; if the bucket is empty, the orchestrator falls back to cached data with a “data from N minutes ago” caveat.
- SendBlue webhook ordering. iMessage delivers multi-part messages out of order occasionally. The orchestrator would respond to part 2 before seeing part 1. Fix: ack-fast inbound webhook (200 OK in <100 ms) + Redis-backed inbound dedupe key (provider message id) + a small wait-and-coalesce window when the first part is detected as a fragment.
- Claude returning JSON in the assistant text. When a tool call failed in a way Claude wasn’t expecting, it would sometimes try to JSON-format the error inside the assistant message. The foreman gets “
{"error": "tool_use_failed"}” instead of a helpful response. Fix: strict response post-processor that flags JSON-shaped responses, rewrites them as plain-English error messages. - Token-rate spikes. A single message thread can grow to 30-40 turns. We were rebuilding the full Claude conversation on every message. Fix: Anthropic prompt-caching on the system prompt + tool definitions block. ~70% token-cost reduction on long threads.
Compliance + audit
Every interaction is logged: the field user’s phone, the verbatim text, the source Forward cited, the verbatim response, timestamp. Writes (RFI drafts, observations, punch items, etc.) require an explicit PM approval click in the dashboard before Forward calls the connected platform’s write API. Logs are exportable as JSON or CSV. Retention follows plan tier: 90 d Standard, 365 d Pro, 7 y Enterprise.
Revoking Forward’s OAuth grant in Procore or Autodesk terminates access immediately; we don’t copy project data — every query is a live read.
What’s next
We’re in early-access pilots. The roadmap is dictated by what real customers actually ask the bot, not by a backlog someone wrote in a Notion doc. The shape we’re seeing: more code-section retrieval (more codes, more depth), better cross-platform queries when both Procore and Autodesk are connected, and a sharper PM approval queue that explains the bot’s reasoning before the PM clicks approve.
How to try it
Text +1 (682) 300-6750 with “Hi Forward demo”. The demo runs against a synthetic commercial project. Try what did RFI 142 say, send me a-301, submittal status for 09 51 13, wire size for 150A continuous on a 200A feeder, 100ft run, or send a photo of any piece of equipment and ask what is this.
Drop your email above for early access on a real project — we’ll wire your Procore + Autodesk + OneDrive in roughly 30 minutes of OAuth + a short scoping call to pick the right pilot.
Try Forward right now
Drop your email above for early access — or skip the form and text +1 (682) 300-6750 from your phone. The live demo answers anything you can ask a project manager in plain English — no signup needed.