Public procurement
An AI bid analyst for public procurement
A supervised agent system with its limits designed in rather than documented: Temporal owns the workflow, and a deterministic policy engine can overrule the model.
Client
A trading and bid team pursuing Canadian federal contracts
Fail-safe
deterministic gate over model output

The challenge
What was in the way
Canadian federal procurement publishes continuously, and qualifying an opportunity is unglamorous and expensive: read the tender, find the mandatory requirements, decide whether the team can meet them, price it, draft.
The solution
What we built
A supervised agent system with its limits designed in rather than documented. Temporal workflows own scheduling, retries, fan-out and human-approval waits; agents run inside activities, so a model call is never on the synchronous path and a timeout is never a lost workflow.
A deterministic policy engine sits above the model: any mandatory requirement evaluating as FAIL or UNKNOWN blocks the bid regardless of what the agent recommends.
Every extracted fact links back to its source text with an immutable hash and a line-addressable citation. The non-goals — no buyer communication, no bid submission, no autonomous price approval — are enforced at the design level, not as warnings.
Key technologies
- Backend
- Python 3.12, FastAPI, SQLAlchemy 2 async, Alembic
- Agents
- PydanticAI with Temporal and OpenAI
- Interface
- React, Vite, TypeScript, Playwright e2e
Impact & results
A working vertical slice
Proving the qualify–price–draft loop end to end.
An architecture that fails safe
The gate is deterministic, citations are verifiable, and the agent cannot act outside review.
A specified production path
A supervisor with six to ten specialist roles, object storage for source documents, OIDC and RBAC.
Start here
Start with a problem, not a brief.
Tell us what is slow, what is manual, what is stalled, or what nobody understands any more. We will tell you honestly whether it is worth building.



