1. The problem: an agent that can spend money
Most agent demos stop at "the model called a tool and it worked". Real back offices have tools you do not want a model to run on its own.
I built a dispatch assistant for a small, made-up field service company. A dispatcher types "What is the status of WO-1043?" or "Order a 3 kW heating element for WO-1044." and the agent answers. It has three tools:
lookup_work_order reads the site, asset, issue, technician and slot. β
Runs on its own.
schedule_visit books a technician for a window. β
Runs on its own.
order_part orders a spare part, and that costs money . β Waits for a person.
And I wanted the whole thing in Dart: the agent server, the tool server and the Flutter client, sharing one set of types. No Python sidecar, no Node service in the middle.
2. Architecture: the agent only knows the back office through MCP
Four pieces, all Dart:
The back office as an MCP server ( genkit_mcp , Streamable HTTP on loopback).β¦