A customer asks a routine question. Someone finds the policy, writes a reply, checks it, and puts it in the right place. None of those steps looks difficult alone. The trouble starts when the request arrives twice, the policy changes, or the process stops halfway through.
A useful automation handles the ordinary path and leaves a clear record when it cannot finish. Start with one small job whose result you can inspect.
Your work product is a workflow definition, a dry-run preview, and a local practice run. The supplied demonstration prepares a fictional Mesa service answer and can stage it in a local review queue after a simulated approval. It cannot send messages, book appointments, access business accounts, or change a live system.
Choose an output with a clear stopping point
“Handle customer service” is too broad for a first project. “Prepare one service-policy answer for review” has a visible beginning and end.
Define the trigger, input, sources, permitted action, reviewer, and outcome. For Mesa, the trigger is a supplied request record. The source is the current inspection policy. The permitted action is staging a review item. Completion means the local queue and its operation record agree that the item was staged.
Customer delivery is a different action. A staged draft is not a sent answer, a confirmed appointment, or a resolved customer case. Keep those distinctions in the workflow and its reports.
Choose a task whose errors can be recognized. If nobody can tell whether an output is right, connecting it to more systems makes the uncertainty harder to manage.
Decide where AI actually helps
Some steps need interpretation: classifying a request, summarizing a long record, or drafting natural language. Other steps need exact rules: checking an ID, comparing a version, adding amounts, or enforcing an approval.
Use ordinary code for exact rules. Place a model only where its flexibility helps, then evaluate that part with representative examples. The demonstration uses a fixed answer template so the control logic can be inspected without an account, API key, or model bill. It is an automation example, not an autonomous agent or a measured AI evaluation.
Anthropic's guide to building effective agents distinguishes workflows with predefined paths from agents that let a model direct more of the process. That distinction is useful when deciding how much freedom a task needs; it does not imply that a more autonomous design is better for Mesa's narrow job.
If a fixed template already produces the needed answer, keep it. You do not need to add a model simply to call the project AI-powered.
Write the input contract before the happy-path prompt
An input contract specifies what a request must contain and what unsupported requests look like. The practice request has these fields:
| Field | Example meaning |
|---|---|
| tenant | The business whose records may be used: mesa |
| event_id | One operation identity: EV-901 |
| case_id and case_version | The request record and the version being reviewed |
| question_type | The narrow supported task: inspection_fee |
| question | Customer text treated as data |
| source_id | The policy required for the draft: SERVICE-01 |
| action | stage_review_item |
| destination | local_review_queue |
The demonstration rejects extra fields and unsupported actions. A caller cannot add approved: true and thereby approve the work. A request for a refund is outside this task and must use a suitable separate process.
In a real application, obtain business identity from trusted account and authorization context. Do not believe an entity name or role merely because a customer or model included it in JSON. The practice harness supplies synthetic actors to demonstrate the checks; it does not authenticate people.
Make a dry run useful to the reviewer
A dry run should show the exact proposed result and the inputs that produced it. “Looks good” is not enough.
The Mesa preview includes the original request, policy version, a source fingerprint, draft text, and explicit false values for booking confirmation and customer sending. The draft gives the $45 inspection fee and credit toward a repair approved within thirty days of inspection. It preserves the lack of appointment confirmation.
The question also asks about Friday. The fixed template does not consult a calendar, so it cannot establish a Friday slot. It produces a partial policy answer that still needs review and any required follow-up.
The preview creates no queue entry or action-ledger row. If a production dry run reads private information, calls a paid model, or creates logs, explain those effects. “Dry run” should describe which actions are suppressed, not promise that absolutely nothing happens.
Keep the path short and explicit
For this first workflow, the path is straightforward:
- Validate the request and actor scope.
- Load the permitted current policy.
- Build an inspectable draft and fingerprint.
- Obtain approval for that exact proposal.
- Recheck conditions and stage one local review item.
- Record and return the result.
Any unsupported input returns a named reason. An expired approval does not quietly become permission to proceed. A missing source does not become an invitation to write from memory.
Write the fallback alongside the automated path. For Mesa, a person can use the current policy manually, preserve unknown availability, and route unresolved questions to the appropriate owner. The fallback still follows the business's rules.
Give each operation an identity
The same event can arrive more than once. A person might click twice, or a sender might repeat a request after a timeout. The automation needs to recognize whether that is the same intended action.
In the demonstration, the combination of business identity and event ID identifies a staging operation. A completed duplicate returns the stored receipt and does not create another queue item. Reusing that ID with changed request content produces a conflict.
AWS's discussion of idempotent APIs explains this pattern: a request identifier allows retries to express the same intent, while changed parameters under the same identifier need explicit handling. The exercise applies that idea to its local queue; it does not prove duplicate prevention across external providers.
Choose the identity to match the business event. If two separate requests happen to ask the same question, they are not automatically duplicates. Text similarity is a poor substitute for an operation record.
Commit the local result and its evidence together
Imagine the queue item is written, then the program fails before recording completion. If those writes are unrelated, the next run might create another item because it cannot find the operation record.
The demonstration places the queue entry, operation receipt, and action audit row in one SQLite transaction. A simulated failure before the commit rolls those action writes back together. SQLite's transaction documentation explains its atomic transaction behavior. This example uses it within one local database.
A different simulated failure happens after the commit but before the caller receives the response. The action exists. On retry, the program finds and returns the original receipt instead of staging again.
An external email service is not part of that SQLite transaction. Adding one would create another boundary to design and test. Chapter 36 explains why you must reconcile an uncertain external outcome before repeating an action.
Run the supplied local example
Download and extract ai-business-part-09-practice.zip. Open a terminal in the extracted part-09 folder, which contains Working-Templates.md and the practice subfolder, then run:
python3 practice/run_demo.py
The default demonstration prints a preview and zero counts for the review queue and action ledger. It uses temporary local files and requires Python with its standard SQLite support. It has no network connection code or API credentials.
Then run:
python3 practice/verify_examples.py
That script exercises simulated roles and approvals, failures, duplicate requests, retrieval boundaries, and recovery. It writes Example-Verification.json. All actual business-approval flags remain false. The test harness's simulated approval is not approval from Randy or Mesa staff.
The source code is included in practice/workflow.py. It is deliberately small enough to inspect, and its README explains which production features it does not implement.
Know what the example has and has not established
Passing a local exercise shows that the supplied code handled the supplied cases. It does not establish that a model will answer correctly, that a connector enforces permissions, or that a real service will behave the same way after an outage.
The exercise uses a trusted test clock and a fixed actor registry. Document and business-record fixtures load into memory. Pause state is also local and resets when the object restarts. Production identity, durable pause controls, secret handling, shared-state consistency, and multiple workers require separate implementation and testing.
Before connecting a real system, identify the added boundary and test it directly. Begin with an appropriate test environment and records. Keep the source, proposal, approval, request identity, and result linked so reviewers can reconstruct what happened.
Define when the pilot is ready to expand
A good first automation finishes the specified job with useful evidence. Measure accepted outputs, complete effort, failed cases, duplicate handling, and successful recovery. Include the work of maintaining sources and resolving exceptions.
Expand only when the next action has a clear purpose and its own permissions and checks. Adding automatic sending is a new business capability, not a minor convenience setting on a draft workflow.
The best first result may be modest: one queue item created correctly, no invented booking, and enough evidence to repeat the work safely. That is a useful foundation for the next step.
Next: Define exactly who can propose, approve, and execute an action in Chapter 33.