We built an internal "First Client Outbound System" to answer a simple question: can an agent reliably find leads, personalize outreach, and keep a pipeline moving without constant babysitting? Short version: not with a single all-in-one agent. What failed first was giving one agent too much responsibility. We tried a prompt that did lead research, scoring, message writing, and follow-up timing in one loop. It looked elegant, but error rates stacked fast. Bad input from lead discovery polluted scoring. Weak scoring produced generic emails. Generic emails killed reply rates. What worked was splitting the system into narrow workers with explicit contracts: 1. Lead finder returns structured fields only
2. Qualifier scores against a fixed rubric
3. Message writer uses only approved fields
4. Scheduler decides next action from state, not free text The key architecture change was forcing every step to output JSON against a schema. No hidden reasoning, no loose text blobs. If a worker could not fill required fields, it had to return "unknown" and pass control forward. A practical pattern that helped: - Store every lead as a state machine: discovered, qualified, drafted, sent, replied, archived