Macha

Build an AI Support Agent in Python (From First Principles)

Abbas, Customer Support & AI, Macha

Written by

Ankeet Guha, Co-founder & CTO, Macha

Reviewed by

Published July 30, 2026

Updated July 30, 2026

Most "AI agent" tutorials either hand you a framework and hide the mechanics, or stop at a chatbot that can't do anything. If you want to actually understand — and own — a support agent, Python from first principles is the clearest way to see what's really happening: it's a loop that calls a model, runs the tools the model asks for, and feeds the results back until the ticket is handled. This guide builds that in plain Python with real code, then is honest about the large gap between working code and a system you'd let answer a customer at 2am — and where a platform closes it.

Build an AI Support Agent in Python (From First Principles)

No framework here on purpose. Frameworks (and platforms) are mostly there to remove the boilerplate you're about to see; seeing it first is how you know what they're doing for you.

What a support agent is, mechanically

Four jobs in a loop: understand the ticket, fetch context (customer, orders, the right help-center article) by calling tools, act (reply, tag, escalate), and know when to stop. In Python, "tools" are just functions plus a JSON schema the model can request. (If you're weighing build-vs-buy before writing any code, our AI agents for customer service overview covers the landscape.)

The agent loop in plain Python

First, pip install anthropic and set your ANTHROPIC_API_KEY. Then define your tools as functions and describe them to the model — Anthropic's tool-use guide documents the exact block shapes:

import anthropic
client = anthropic.Anthropic()

def get_customer(email): ...          # your DB / help-desk API
def get_recent_orders(customer_id): ...
def reply_to_ticket(ticket_id, body): ...

TOOLS = [{
  "name": "get_customer",
  "description": "Look up a customer by email.",
  "input_schema": {"type": "object",
      "properties": {"email": {"type": "string"}}, "required": ["email"]},
}]  # ... one entry per function

DISPATCH = {"get_customer": get_customer,
            "get_recent_orders": get_recent_orders,
            "reply_to_ticket": reply_to_ticket}

Then the loop itself — this is the whole "agent," ~20 lines:

def run_agent(ticket_text):
    messages = [{"role": "user", "content": ticket_text}]
    while True:
        resp = client.messages.create(
            model="claude-sonnet-4-6", max_tokens=1024,
            system=SYSTEM_PROMPT, tools=TOOLS, messages=messages)
        if resp.stop_reason != "tool_use":
            return resp.content[0].text          # final answer
        messages.append({"role": "assistant", "content": resp.content})
        results = []
        for block in resp.content:
            if block.type == "tool_use":
                fn = DISPATCH[block.name]
                out = fn(**block.input)           # run your function
                results.append({"type": "tool_result",
                    "tool_use_id": block.id, "content": str(out)})
        messages.append({"role": "user", "content": results})

Run it and you get a real interaction — the model calls your tools, then answers:

>>> run_agent("Where's my order #4471? — [email protected]")
[tool] get_customer(email='[email protected]')     -> {'id': 'c_88', 'plan': 'Pro'}
[tool] get_recent_orders(customer_id='c_88')   -> [{'id': 4471, 'status': 'shipped', 'eta': 'Jul 6'}]
"Hi Jane — order #4471 shipped and should arrive Jul 6. Here's your tracking link…"

That's the whole loop working, and the same shape applies to the OpenAI Python SDK (you read tool_calls off the response instead of tool_use blocks). But right now the tools are stubs.

From stubs to real tools

The stubs are where a demo becomes real work. reply_to_ticket has to actually call your help desk's REST API, with auth and error handling:

import requests

ZENDESK = "https://yourco.zendesk.com/api/v2"
AUTH = (f"{EMAIL}/token", API_TOKEN)

def reply_to_ticket(ticket_id, body):
    r = requests.put(f"{ZENDESK}/tickets/{ticket_id}.json",
        json={"ticket": {"comment": {"body": body, "public": True}}},
        auth=AUTH, timeout=10)
    r.raise_for_status()                 # you handle 429s, retries, token refresh
    return {"status": "sent"}

And the agent has to be triggered by a new ticket, so you stand up a webhook:

from fastapi import FastAPI, Request
app = FastAPI()

@app.post("/zendesk-webhook")
async def on_ticket(req: Request):
    payload = await req.json()
    verify_signature(req)                # untrusted input — verify + dedupe
    run_agent(payload["ticket"]["description"])
    return {"ok": True}

Multiply that by every tool (get_customer, get_recent_orders, a search_kb retriever over your embedded help center) and every internal system. It runs — but it's still nowhere near production, and Python makes that painfully explicit, because you wrote every line, so every gap is yours.

Where Claude Code and Codex help

You can have Claude Code or Codex scaffold all of the above — the tool functions, the dispatch loop, the help-desk client, the tests — from a one-line description, then refine. It writes the boilerplate fast; it doesn't decide your tools, guardrails, or escalation rules, and it won't run the agent in production.

What "production" adds to those 20 lines

Here's the honest gap, and in pure Python every item is code you write and own:

  1. Real tools, not stubsget_customer/reply_to_ticket become Zendesk/Freshdesk API clients: OAuth and token refresh, pagination, rate-limit handling, and a webhook endpoint (Flask/FastAPI) to trigger the agent per new ticket, with signature verification and idempotency.
  2. Retrieval — chunk and embed your help center, store vectors (pgvector/FAISS), back the search_kb tool, and re-embed when docs change.
  3. Guardrails — grounding checks, PII redaction, action limits (cap refund amounts), prompt-injection defenses (tickets are untrusted input), and an escalate path with a clean human handoff.
  4. State & robustness — conversation/context-window management, try/except with retries and backoff around every model and tool call, and a queue so a spike doesn't drop tickets.
  5. Hosting 24/7 — a cloud host, secrets management, workers, a dead-letter queue, autoscaling.
  6. Observability — log the full trace of every run (tools called, context, decision), plus latency/cost metrics and alerting.
  7. Evaluation — a harness over real historical tickets with automated scoring, run as a regression before every prompt or model change.
  8. Maintenance — model deprecations, help-desk API changes, KB re-embedding, on-call.

That's weeks of work and permanent upkeep — and none of it is the interesting 20 lines. It's the undifferentiated plumbing every support agent needs.

In Macha's Custom Tools, real REST APIs become agent-callable tools — defined by endpoint and auth or built by AI from a sentence — so you skip writing and maintaining an API client per integration.
In Macha's Custom Tools, real REST APIs become agent-callable tools — defined by endpoint and auth or built by AI from a sentence — so you skip writing and maintaining an API client per integration.

The shortcut: keep the Python thinking, drop the plumbing

The valuable part of what you just built is the design — which tools, what guardrails, when to escalate. Macha is the layer that runs that design without the plumbing underneath it:

  • Tools without clientsCustom Tools turn any REST API into an agent tool (define endpoint + auth, or let the AI builder create it from a sentence). Your help desk is a native connector (Zendesk, Freshdesk, Front, Intercom, HubSpot, Help Scout, Salesforce, Jira Service Management, Pylon); internal APIs plug in the same way — no requests client to write or maintain, no webhook endpoint to host.
  • Grounding, hosting, retries, queue — attach your help center as a source; the agent runs in the cloud, triggered by tickets, with retries handled.
  • Observability + eval — agent analytics show every run and tool call; Studies grade the agent against a batch of real tickets so changes are measured.
Macha's Connectors page — native help-desk and app integrations an agent's tools attach to, alongside custom ones, without building each API client yourself.
Macha's Connectors page — native help-desk and app integrations an agent's tools attach to, alongside custom ones, without building each API client yourself.

From scratch (Python) vs. on a platform

ConcernPure PythonPython design + Macha
Agent loopYou write it (~20 lines)Built in
Tools / API clientsYou write + maintain eachCustom Tools / native connectors
RetrievalYou build + run a vector storeAttach sources; handled
Guardrails / escalationYou build enforcementYou configure it
Hosting, queue, retriesYour infraRuns in the cloud
Observability + evalYou build bothAgent analytics + Studies
Time to productionWeeks + ongoingDays

So which should you build?

Write it in pure Python if you're learning how agents work, you need total control of the runtime, or you have constraints (on-prem, data-residency) a SaaS can't meet — the 20-line loop is genuinely worth understanding either way. (See our from-scratch vs. platform breakdown for the full comparison.) Reach for a platform when resolving support is the goal and you'd rather not maintain eight moving parts of plumbing forever. You can start free on Macha and wire your first tool in minutes — bringing the same design thinking, minus the boilerplate.

FAQ

Do I need LangChain or an agents SDK? No — the loop above is all an agent fundamentally is. Frameworks add structure (and their own concepts) on top; a platform removes the infrastructure underneath. Start raw to understand it, then decide what you actually want to own.

Does this work with OpenAI instead of Anthropic? Yes — same shape with the OpenAI Python SDK: you read tool_calls off the response, run your functions, and append tool messages back. The production gap (steps 1–8) is identical regardless of model.

Can Claude Code or Codex just build the whole thing? They'll write the code fast — loop, tool functions, API client, tests. They won't make the product decisions or host, monitor, and evaluate the agent in production.

How do I know it's good before it touches customers? Grade it against real historical tickets with automated scoring, re-run before every change. Build the harness yourself or use something like Macha's Studies.

Macha

About Macha

Macha is an AI agent platform that works on top of the help desk you already use — Zendesk, Freshdesk, Gorgias, or Front — and connects to the rest of your stack, even your own internal systems. Its AI agents resolve tickets and automate entire workflows end to end, all set up in plain English, no code. Learn more about Macha →

Zendesk
5.0 on Zendesk Marketplace

Loved by support teams worldwide

See what support teams are saying about Macha AI.

The application seems excellent to me! We are still testing, and we need support for some details and they were extremely efficient too!

Daniela Costa

Daniela Costa

Head of Support, Seabra

Macha has been a great addition to our support toolkit. It generates clear, well-organized responses that fit naturally into our workflow. One feature we particularly appreciate is its ability to automatically reply in the same language as the ticket.

Marius F

Marius F

Support Head, Zentana

We've been using Macha for a little while now and it's been really great addition so far! It's powerful, convenient, and makes getting work done a lot easier for our agents.

Alexander Wedén

Alexander Wedén

Head of Support

Support team is very helpful and responsive. Really enjoy how lightweight this is within Zendesk itself vs other more intrusive tools.

Cathleen Wright

Cathleen Wright

Zendesk Admin, Cortex IO

So far it's pretty good! Our queries are a little nuanced, so we can't always use it, but it's got enough utility for us. It can even incorporate our bilingual country with greetings in a second language.

Jae Oliver

Jae Oliver

Head of Support, Wise

Really enjoying using Macha, it has made a noticeable difference to our support team in a short amount of time. I really like the ticket summary feature, saves us a lot of time.

Harry Jackson

Harry Jackson

Head of Support, Crumb

Macha AI is a great addition to my workspace! It's powerful, convenient, and it really makes productivity so much easier for our agents!

Dave G

Dave G

Head of Support, Cyber Power Systems

Very impressed! AI integration for Zendesk has certainly come a long way and Macha seems to set the standard for now. This will for sure save lot of time in our support team.

Pauli Juel

Pauli Juel

Head of CS, Dokument24

Macha has been working great for us so far! The auto-responses are accurate and our resolution time has dropped significantly.

Lana T

Lana T

Zendesk Admin, Swotzy

Macha AI is a great addition. The knowledge base feature means our agents always have the right answers at their fingertips.

Mischa Wolf

Mischa Wolf

Head of Support, Topi

We're enjoying this integration so far. It's made our support team more efficient and our customers get faster responses.

Paula G

Paula G

Head of Customer Support, Xly Studio

The team enjoys using it. It saves considerable time on common questions and the integration options are excellent.

Kilian Leister

Kilian Leister

Support Head, Didriksons

Ready to supercharge your team with AI?

Get started in minutes. Connect your tools, configure your agents, and let AI handle the rest.

500 free credits · no time limit, no credit card