Tutorial: Build A Support Agent
Build a support agent that reads example tickets and customers from JSONPlaceholder, follows a triage skill, and saves investigation notes. The demo API needs no connection credentials. Model access is provided by your Amodal organization.
1. Create The Repo
Create a GitHub repo with this tree:
amodal.json
amodal/
connections/support-demo/
spec.json
policy.json
surface.md
knowledge/
support-policy.md
skills/
triage/SKILL.md
stores/
investigation-notes.json
agents/
default/
AGENT.md
agent.json
evals/
ticket-triage.md
account-owner.mdConnect the repo to an agent in Amodal, or use Build With A Coding Agent to create and connect it with the Platform API.
2. Add amodal.json
{
"name": "support-demo",
"version": "0.1.0",
"description": "Tutorial agent for support-ticket triage"
}Add the default chat instructions in agents/default/AGENT.md:
# Support Agent
Help the support operator investigate tickets using the support-demo connection.
Load the Triage skill and the support-policy knowledge document before working.
Check the ticket and its customer before recommending an action. Save an investigation note when the operator asks.
Do not include customer email addresses in your answer.Select its capabilities in agents/default/agent.json:
{
"name": "Default",
"tools": ["load_skill", "load_knowledge"],
"skills": ["Triage"],
"connections": ["support-demo"],
"stores": {
"investigation-notes": "rw"
}
}The runtime selects default when a chat request omits agent. AGENT.md is required; a directory containing only agent.json is ignored. Skill entries use the parsed skill name: Triage matches the # Skill: Triage heading below.
Model selection is platform state, not an amodal.json field. If you do not choose a model, the platform default is Gemini 3.5 Flash.
3. Add A Public Connection
amodal/connections/support-demo/spec.json:
{
"baseUrl": "https://jsonplaceholder.typicode.com",
"format": "rest",
"testPath": "/todos/1"
}This API is public, so there is no auth block and no secret to configure.
amodal/connections/support-demo/surface.md:
# Support Demo API
This is a fake support system backed by JSONPlaceholder.
Use these read-only endpoints:
- `GET /todos/{id}`: load a fake support ticket.
- `id` is the ticket ID.
- `userId` is the related customer ID.
- `title` is the issue summary.
- `completed` means the issue is resolved.
- `GET /users/{id}`: load the fake customer account.
- `id` is the customer ID from the ticket's `userId`.
- Summarize `name` and `company.name`; omit `email`.
When asked about a ticket, first load `/todos/{id}`. If the ticket includes a `userId`, load `/users/{userId}` before recommending action.amodal/connections/support-demo/policy.json:
{
"endpoints": {
"*": {
"returns": [],
"confirm": "never",
"reason": "This tutorial only reads from the API."
},
"GET /todos/{id}": {
"returns": ["Ticket"]
},
"GET /users/{id}": {
"returns": ["Customer"]
}
}
}The fallback * rule blocks write requests. The GET entries name expected response entities; they do not limit which GET paths can be requested. The prompt asks the model to omit email addresses. This tutorial does not configure enforced field redaction; see Security before using real customer data.
4. Add Knowledge
amodal/knowledge/support-policy.md:
---
description: Rules for reporting support investigations and recommending next actions.
---
# Support Policy
- State which ticket and customer records were checked.
- Treat `completed: true` as resolved and `completed: false` as still open.
- Separate confirmed facts from assumptions.
- Do not expose credentials, payment tokens, or private internal notes.
- When data is missing, ask for the missing ticket or customer identifier.
- End with one concise next step for the support operator.The initial prompt lists knowledge documents by name and description. Their bodies are read with load_knowledge, which this agent declares in its tools list. Put reference policy here and task instructions in skills. Instructions that must apply before any tool call belong in AGENT.md.
5. Add A Skill
amodal/skills/triage/SKILL.md:
# Skill: Triage
Use this workflow for support-ticket questions.
Trigger: When the user asks about a ticket, customer issue, support case, or next operator action.
## Behavior
1. Identify the ticket ID from the user message.
2. Load `GET /todos/{id}` from the `support-demo` connection.
3. If the ticket has a `userId`, load `GET /users/{userId}`.
4. Summarize confirmed facts:
- ticket ID
- issue title
- open/resolved state
- customer name or company when available
5. Recommend one next support action.
6. If useful, write a short record to `investigation-notes`.
## Constraints
- Do not invent ticket fields that are not returned by the API.
- Do not call write endpoints; this demo connection is read-only.
- If the API call fails, explain that the ticket could not be loaded.6. Add A Store
amodal/stores/investigation-notes.json:
{
"name": "investigation-notes",
"entity": {
"name": "InvestigationNote",
"key": "{ticket_id}",
"schema": {
"ticket_id": { "type": "string" },
"summary": { "type": "string" },
"next_action": { "type": "string" },
"confidence": {
"type": "enum",
"values": ["low", "medium", "high"]
}
}
},
"history": { "versions": 3 },
"trace": true
}This gives the agent a structured place to persist a concise note per ticket. The generated store tools will be named store__investigation_notes__get, store__investigation_notes__set, store__investigation_notes__query, and so on.
7. Add Evals
evals/ticket-triage.md:
# Eval: Ticket Triage
Tests whether the agent checks ticket data before recommending action.
## Setup
Context: Ticket 1 exists in the demo support API.
## Query
"Triage ticket 1. What should the operator do next?"
## Assertions
- Should load or reference ticket 1 before answering
- Should identify whether the ticket is open or resolved
- Should provide one concise next action
- Should NOT invent private customer dataevals/account-owner.md:
# Eval: Account Owner
Tests whether the agent follows the ticket's userId to the customer record.
## Setup
Context: Ticket 1 has a related userId.
## Query
"Who owns ticket 1 and what is the issue?"
## Assertions
- Should check the ticket record
- Should use the ticket's userId to check the related customer
- Should summarize the issue title
- Should avoid unnecessary personal details8. Deploy
Commit and push the repo. In Amodal:
- Open the agent.
- Open Source and confirm the source files are visible.
- Open Deploys > Source and deploy the selected version.
- Wait for the build and runtime to be ready.
- Use Make production when the tested deploy should serve the persistent agent URL.
Before chatting, check Connections. The support-demo connection should show the files from amodal/connections/support-demo/ and the health check should be able to reach /todos/1.
9. Smoke Test
Ask these in the deployed chat:
Triage ticket 1. What should the support operator do next?
Who owns ticket 1, and what company are they associated with?
Triage ticket 2 and save a short investigation note.The answer should identify the checked ticket, use its returned title and completion state, load the related customer, and give one next support action.
If the answer is generic and does not mention tool data, inspect:
- Sessions: confirm there is a
requesttool call. - Logs: check for connection, auth, or provider errors.
- Prompt: confirm the
Triageskill and support policy loaded. - Guardrails: confirm the connection policy blocks writes.
- Deploys: confirm production points at the deploy that contains these files.
10. Run Evals
Open Evals and run the two eval files. Review the first run before using it as a baseline. After changing source, redeploy and rerun the evals.
Good first iterations:
- Tighten
amodal/skills/triage/SKILL.mdso the agent always loads the related customer. - Add a knowledge rule that unresolved tickets should end with a next operator action.
- Add another eval for ticket
2. - Ask the agent to save an investigation note and verify the store tool call appears in the session.
11. What To Build Next
Once this tutorial works, replace the demo API with your real system:
- Change
amodal/connections/support-demo/spec.jsonto your API base URL and auth. - Update
surface.mdwith your real endpoints and field meanings. - Tighten
policy.jsonbefore enabling write endpoints. - Add secrets in Amodal instead of committing credentials.
- Add evals for your highest-risk support behaviors.