AI Agents Will Eat Your Busywork in 2026: Build One

Your inbox, invoices, and follow-ups eat the first two hours of every day, and the advice online is a syllabus: vector databases, ML theory, a career roadmap. You don't need a new career. You need one boring task handed off to a small loop of code. Here's one way to build it, where it can break, and a checklist for picking your first task.
What an agent actually is: a loop with three steps
An AI agent is a loop with three steps: observe, decide, act. Observe means it reads something (an email, a form submission, a message). Decide means a language model picks from a short list of options. Act means code does something about it: sends a message, files a record, creates a document.
Everything else you hear about (planning, memory, tools) is a variation on that loop. Anthropic's engineering team draws a useful line in Building Effective AI Agents: workflows run LLMs and tools through predefined code paths, while agents are systems where the LLM dynamically directs its own processes and tool usage. Simon Willison's shorthand is that an agent runs tools in a loop to achieve a goal.
By that definition, the design in this post sits closer to a workflow with an LLM decision step than to a free-roaming agent. That's deliberate. Anthropic's own guidance is to find the simplest solution possible and add complexity only when needed. For a one-person business, the constrained version is the one you can trust.
It's also worth being skeptical of the label. Gartner has warned about "agentwashing," meaning vendors calling AI assistants that depend on constant human input "agents." Gartner also forecasts that 40% of enterprise applications will include task-specific AI agents by the end of 2026, up from less than 5% in 2025, per its August 2025 press release. That's a forecast about enterprise software, not a measurement, and it says nothing about your five-person shop. The takeaway for you: the skill isn't building the loop from scratch. It's knowing which boring task deserves one.
The email triage agent, step by step
Here's one way to build it. The agent can run on a small server you control rather than a cloud cluster. An email lands in Gmail, the agent fetches it, strips the signature and quoted history, and sends the cleaned text to a language model with a very short prompt.
The prompt asks for exactly three things:
- A category: client request, invoice or payment, lead, or noise.
- A one-sentence summary.
- A suggested next action, chosen only from a fixed list.
That last constraint matters most. The model never invents actions. It picks from a menu. Here's the shape of the core loop:
ALLOWED_ACTIONS = ["reply_needed", "pay_or_invoice", "follow_up_lead", "archive"]
ALLOWED_CATEGORIES = ["client_request", "invoice_payment", "lead", "noise"]
def triage(message):
clean = strip_signature_and_quotes(message.body)
clean = strip_forwarded_headers(clean)
raw = call_model(
system=TRIAGE_PROMPT, # short: categories, 1-line summary, action menu
user=clean,
)
result = parse_json_strict(raw) # reject malformed output, never act on it
if result["category"] not in ALLOWED_CATEGORIES:
return escalate_to_human(message, reason="bad category")
if result["action"] not in ALLOWED_ACTIONS:
return escalate_to_human(message, reason="bad action")
return result
def run_once():
for msg in fetch_unread_via_gmail_api():
result = triage(msg)
if result["category"] == "noise" and not has_money_signal(msg):
archive(msg)
else:
push_to_telegram(msg, result) # approve / ignore buttons
Four steps: fetch unread messages through the Gmail API, build the prompt from the cleaned body, call the model and force structured JSON (a malformed reply gets rejected, not acted on), then route by category. Noise gets archived. Everything else goes to your phone as a Telegram message: category, one line, suggested action, and two buttons, approve or ignore.
The loop itself is short, and much of the code ends up being error handling rather than AI.
Polling vs. push: a detail that will bite you
Fetching on a schedule is the simplest thing that works. If you want near-real-time delivery, Gmail's push notifications come with traps, based on secondary sources such as this Nylas guide and this Unipile write-up. Check Google's own Gmail API documentation to confirm the details before relying on them:
- Gmail delivers through a Cloud Pub/Sub topic, not a direct webhook.
- A notification carries only the user's email address and a new
historyId, not the message content. You then callusers.history.listto find out what changed. - A
users.watchsubscription expires after a limited period (reported as about seven days). If you miss the renewal, notifications can stop silently, with no error.
If you go push, build a renewal job and an alert for "no notifications in N hours" on day one. For a first agent, polling every few minutes is fine and has nothing to expire.
Where it can break (and the rules that fix it)
Working code, working system, so here are the failure modes to watch for. These are typical examples, not a log of specific incidents.
Failure mode 1: a friendly payment reminder gets classified as noise. A client's polite reminder about an overdue amount can read like small talk to the model. That's a mistake with real cost. The fix isn't a smarter model. It's a hard rule in code: anything mentioning an amount, an invoice number, or a due date can never be auto-archived. It always goes to a human.
import re
MONEY_PATTERNS = [
r"[$€£]\s?\d", # currency amounts
r"\binvoice\s*(no\.?|#|number)?\s*\w*\d+",
r"\bdue\s+(on|by|date)\b",
r"\b(overdue|past due|payment)\b",
]
def has_money_signal(msg) -> bool:
text = (msg.subject + " " + msg.body).lower()
return any(re.search(p, text) for p in MONEY_PATTERNS)
Failure mode 2: a forwarded thread gets summarized as if the forwarder wrote it. The model can attribute the content to the wrong person. Fix: clean forwarded headers (---------- Forwarded message ----------, From:/Date: blocks) before the model ever sees the text.
Failure mode 3 is a policy, not a bug: the agent never sends anything outward on its own. Reading and summarizing are automatic. Anything that leaves your business (a reply, an invoice, a payment) waits for a tap from a human. That's the difference between an agent you trust and one that embarrasses you.
Notice the pattern: none of these fixes involve a bigger model. They're deterministic rules wrapped around the model. When the stakes are money, code beats prompting.
Same loop, different job: invoices from messy requests
The loop transfers to other domains unchanged. Picture a small invoicing business where someone hand-types invoices from customer requests all week. The agent version:
- Observe: a request arrives with a customer name and a list of items.
- Decide: the model extracts the fields and checks them against the customer list, flagging anything it can't match.
- Act: code generates the invoice in the right format and drops it in a review folder.
A human checks the flagged ones and approves the rest in a batch. The model isn't doing anything magical here. It's turning messy text into clean fields, and code does the rest. That's where most of the business value from agents lives right now: messy input in, structured output out, human approval on anything that matters.
INVOICE_SCHEMA = {
"customer_name": str,
"line_items": [{"description": str, "qty": int, "unit_price": float}],
}
def process_request(text):
fields = extract_fields(text, INVOICE_SCHEMA) # LLM, strict JSON
customer = match_customer(fields["customer_name"]) # plain code, fuzzy match
if customer is None or not totals_check(fields):
return move_to("needs_review", fields) # flagged for a human
draft = render_invoice(customer, fields) # plain code
return move_to("ready_for_approval", draft) # never auto-sent
The LLM touches one step. Matching, math, rendering, and filing are ordinary code, which is why the system is predictable.
What it costs, and how to measure it before you build
On hardware you already own, compute is basically electricity. The model calls are the only real expense, and email-sized text is tiny. One aggregator, Sentra's Claude API pricing breakdown, lists Claude Haiku 4.5 at $1 per million input tokens and $5 per million output tokens, and recommends that tier for classification, routing, and short summaries. Check Anthropic's official pricing page before you commit, since aggregators disagree on other models' prices and rates change.
Here's labelled example math with round numbers. Say each email is about 500 input tokens and the reply is about 100 output tokens, at 100 emails a day:
Input: 100 emails x 500 tokens = 50,000 tokens/day
Output: 100 emails x 100 tokens = 10,000 tokens/day
At $1/M in and $5/M out:
input = 0.05M x $1 = $0.05/day
output = 0.01M x $5 = $0.05/day
total = $0.10/day, roughly $3/month
That's an illustration, not a billing statement. Your prompt length and volume will differ, so log your own:
# one line per processed email: easy to total up later
echo "$(date -Is),${msg_id},${input_tokens},${output_tokens},${category}" \
>> ~/triage/usage.csv
Also measure the before: emails per day, minutes you spend triaging now, and cost per model call. If you can't measure the before, you can't prove the after, and you'll never know whether the agent earned its place.
If you'd rather not write the glue code, n8n has a self-hosted option, so you pay only for your server; see this n8n pricing breakdown and confirm the current license terms on n8n's own site. I haven't compared it feature-by-feature against a hand-rolled script, so treat that as an option to evaluate, not a recommendation.
The checklist: pick your first task
A task is a good first agent if it passes all five checks:
- You do it at least daily. Frequency is where the hours hide.
- It follows rules you could write on a sticky note. If you can't explain how you decide, the model can't guess it reliably.
- A mistake is cheap and reversible. Triage and summaries are low risk. Sending money is not.
- The input is text or a document. That's what models handle best.
- You can keep a human tap between the decision and anything irreversible.
If a task fails check 3 or 5, start with something else.
Here's how to start this week:
- Pick one task.
- Write down, in plain language, the three or four categories it falls into and what you do for each. That list becomes your prompt.
- Build the smallest version that only observes and summarizes. No actions at all.
- Run it alongside your normal routine for a week.
- Compare its calls to yours. Every disagreement is either a prompt gap or a missing rule, and each one you fix is a hard-coded rule like the money-signal check above.
Only after a week of agreement should you let it archive anything, and only after that should you consider any outward action, with a human tap still in front of it.
Why bizflowai.io helps with this
I'm a senior engineer who builds practical AI automation for solopreneurs and small teams, and the approach in this post is the one I favor: constrained loops with fixed action menus, hard-coded guardrails around money, and nothing sent outward without a tap. If you'd rather hand off the build than learn the Gmail API, you can find me at bizflowai.io; if you'd rather build it yourself, the checklist above is a solid way to scope your first project.
Want more like this?
I publish practical AI automation tutorials.
Planning an AI automation project or need a second opinion on your architecture?
Connect with me on LinkedIn — Lazar Milićević, senior engineer.
Visit bizflowai.io for services and case studies.
Frequently asked questions
What is an AI agent?
An AI agent is a loop with three steps: observe, decide, act. Observe means it reads something, such as an email, a form submission, or a message. Decide means a language model looks at what it read and picks from a short list of options. Act means code does something about it, like sending a message, creating a file, or updating a record. Planning, memory, and tools are variations on this loop.
How does an AI email triage agent work?
The agent fetches unread Gmail messages through the Gmail API, strips signatures and quoted history, and sends the clean text to a language model with a short prompt. The model returns a category (client request, invoice or payment, lead, or noise), a one-sentence summary, and a suggested action from a fixed list. The answer is forced into structured JSON, then routed: noise is archived and everything else goes to Telegram for approval.
How do I keep an AI agent from making costly mistakes?
Use guardrails. Let the model choose actions only from a fixed menu, force output into structured JSON so malformed replies are rejected, and add hard rules, such as never auto-archiving anything that mentions an amount, invoice number, or due date. Most importantly, let the agent read and summarize automatically, but require a human tap before anything leaves your business, such as a reply, invoice, or payment.
What are AI agents best used for in a small business?
Most business value from agents right now comes from turning messy input into structured output, with human approval on anything that matters. Examples include triaging email and generating invoices from customer requests. In the invoicing case, the model extracts fields and flags unmatched customers, code generates the invoice into a review folder, and a human approves in batch. The key skill is knowing which boring task deserves an agent.
How much does it cost to run an AI agent, and how do I measure if it's worth it?
Running on a machine you already own, compute is basically electricity, and the model calls are the only real expense. For email-sized text those calls are tiny. Before building, log real numbers: how many emails you get per day, how long triage takes you now, and what a model call costs per message. If you can't measure the before, you can't prove the agent earned its place.