AgentMeshLog inStart free

Build guides

Build a support agent that answers a refund ticket

This is the whole build, in order, with every field named as it appears on screen. It takes about ten minutes on the free plan, which needs no card. At the end you will have an agent that reads a refund ticket, looks up the order, and drafts a reply — and you will have seen it get one wrong on purpose.

I wrote this by doing it. Every number below came out of runs on the live product, and the one thing I would not skip is step 6.

Before you start

  1. A free account. No card, nothing to install.
  2. Ten minutes. Six of the eight steps take under a minute each.
  3. Nothing else. You do not need an API of your own — step 4 uses a public one so the build works before you wire anything up.

Step 1 — create the agent

Go to Agents → Create agent. The form has six fields and only one of them decides how the agent behaves.

FieldWhat to putDoes it change behaviour?
Agent NameRefund Ticket ResponderNo — it is how you find it later
TypeCUSTOMER_SUPPORTNo. It labels the agent and picks its icon. It is never sent to the model
DescriptionAnything useful to youNo. Also never sent to the model
Tagssupport, refundsNo
ToolsLeave for step 4Yes
Configuration (JSON)See step 2Yes. This is the one

That third column is the thing to know before anything else. There is no "instructions" field on this form. A well-written Description changes nothing about what the agent does.

Step 2 — write its instructions in the Configuration box

The instructions live under system_prompt in the Configuration (JSON) box. Paste this:

{
  "system_prompt": "You are a support agent for an online shop. For each message: classify it (billing, delivery, returns, other), look up any order number you are given using the http_request tool, and draft a reply in plain, warm English. Never say you have checked something unless the tool call actually returned the data. If a lookup fails, say you are checking and escalate instead of guessing.",
  "temperature": 0.3
}

Two things worth knowing about that box:

  1. **Only some keys do anything.** The engine reads `system_prompt`, `model_config`, `tools`, `input_fields`, `timeout`, `max_retries` and `response_format`. Invented keys like `escalation_threshold` or `languages` are stored and never read — they look like configuration and are decoration.
  2. `temperature` at 0.3 keeps replies steadier than the 0.7 default. For customer-facing text that is usually what you want.
  3. If the JSON is invalid the Save button stays disabled, so you cannot lose the prompt to a typo.

Save. The agent now exists and is Inactive — that is deliberate, so nothing runs or spends tokens before you meant it to.

Step 3 — run it once before giving it any tools

Toggle the agent to Active, click Run, and paste this as the input:

Subject: Charged twice for my October invoice

Hi, I was billed 29 USD twice on 3 October, order #A-4471 and #A-4472.
Same card, same day. I only ever had one subscription. Please refund one
of them. This is the second time I have had to write about billing.

You get a reply in a few seconds. It will be reasonable and it will be invented — it has no way to look up those orders yet. That is the point of running it now: you have just seen what the model does with no access to anything, which is the baseline every later step is measured against.

Step 4 — give it one tool

Open the agent, click Edit, and in the Tools section tick http_request. Save.

The checkbox does not just set a permission — it writes "tools": ["http_request"] into the Configuration JSON for you. Open the box again and you will see it there. You never hand-write that key.

What ticking it allowsWhat it still does not allow
Any public REST API, any method, with your own headersAnything on a private or internal address — an SSRF guard blocks those before the request is made
1,000 calls per dayMore than three redirect hops, each one re-checked
Credentials you pass as headersThose headers surviving a redirect to a different host — they are stripped

Run the same input again. This time the reply should mention having tried to look the orders up. The next step is where you find out whether it really did.

Step 5 — read the run, not the status

Open the run from Executions. Ignore the green badge at the top and read the step rows underneath. Each one records:

  1. What the step **received** — the field that tells you where a problem started.
  2. What it returned.
  3. Its status and duration.
  4. Its tokens and cost, on agent steps.
  5. Every tool call, with its arguments and its result.

Look at the tool call. It has both an ok and a status. Those are different questions — and step 6 is about what happens when they disagree.

Step 6 — break it on purpose

Do not skip this. It costs a fraction of a cent and it is the most useful thing on this page.

  1. Edit the `system_prompt` and tell it to look up orders at `https://fakestoreapi.com/carts/{order}` — an endpoint that will refuse you.
  2. Run the same ticket again.
  3. Open the run and read the tool result.

You will see something like "ok": true, "status": 403. The HTTP request completed, so the tool reported success — and the 403 means it got nothing back. An agent reading that as data will write to your customer as though it had the order in front of it.

Source: that exact run of mine, published in full. It finished COMPLETED, cost $0.0204, took 28.5 seconds, and the reply it drafted told the customer it could see a duplicate charge it had never read.

What to do about it

Two things, and the first is free: keep a person on the send button while you are learning what the agent does. Drafting is where the value is; sending is where the risk is.

The second is the instruction already in your prompt: *never say you have checked something unless the tool call actually returned the data.* It helps and it is not a guarantee — the model is being asked to police itself. The reliable check is you reading the tool result’s status.

Step 7 — what it cost you

The run page shows your own numbers. For comparison, measured runs of this exact shape:

The runTimeCost
Triaged and answered8.4 seconds$0.0144
Answered and escalated to a human28.5 seconds$0.0204
Failed on its first tool call4.1 seconds$0.0024

Source: rows one and three are the worked example; row two is the logged run linked above. So a hundred tickets a month is somewhere near a dollar and a half of usage — which means cost is not the thing to think hard about here. Correctness is.

The free plan allows 100 runs or $0.50 of usage a day, whichever comes first.

Step 8 — make it two agents

Once one agent works, split it. A Triage agent that classifies and returns structured JSON, then a Reply agent that drafts from those fields. Turn on the JSON-output checkbox on the first one — it writes "response_format": "json" into its Configuration for you — and a later step or condition can then read its fields by name instead of parsing prose.

The reason to split is not capability, it is diagnosis: when one prompt doing four things goes wrong you cannot tell which of the four broke. Full walkthrough: Build a multi-agent workflow.

Next

  1. Let it run without you — see Automate: schedules & webhook triggers.
  2. Read a run that went wrong — see How to troubleshoot a failed run.
  3. See the other nine tools and their daily caps — see Give agents tools & integrations.