Appointment scheduling support
The complete company flow: the agent consults services and availability in your operation's API, identifies the customer and creates the appointment — with a knowledge base for what doesn't change.
Updated on Sep 02, 2026
This is the flow most companies actually need: an attendant who doesn't know anything by heart. Price, availability, registration, and scheduling all come from the system, in real time — and the conversation happens on the channel where the customer already is.
It's a real production agent, with the business swapped for a fictional one. The seven routes, the prompt design, and the split between RAG and API are the originals.
The split that stops the agent from hallucinating
Knowledge base for what doesn't change (service area, how the service works, policy). Webhook for what changes every minute (price, availability, registration, scheduling). The prompt states this explicitly — and that's why the agent doesn't make up prices.
How to import
On the platform: Agents → Import, choose the downloaded file. It enters as a new draft (nothing existing is changed), with observability IDs renewed. Then fill in what belongs to your environment — credentials, URLs, and knowledge bases — and publish.
The complete file has the seven routes. Here's the structure and two of them — one read with query string and one write with body:
{
"format": "hinow.agent",
"version": 1,
"agent": {
"name": "Atendimento com agenda",
"system_prompt": "Você é o atendente da Clínica Movimento … (o prompt inteiro está no arquivo)",
"workflow": {
"nodes": [
{ "id": "start", "type": "start", "data": { "label": "Início", "variables": [] } },
{ "id": "agent-1", "type": "agent", "data": { "name": "atendente", "model": "hinow/himax" } },
{ "id": "rag-1", "type": "rag_search", "data": { "label": "Base de conhecimento",
"config": { "rag_ids": [], "top_k": 4, "min_score": 0.3 } } },
{ "id": "webhook-1", "type": "webhook", "data": { "label": "Sistema da empresa",
"config": {
"name": "API da agenda",
"baseUrl": "https://api.suaempresa.com/tools",
"timeout": 30000,
"auth": { "type": "bearer", "token": "COLE_SEU_TOKEN_AQUI" },
"retryOnError": true,
"maxRetries": 2,
"routes": [
{
"name": "verificar_cliente",
"method": "GET",
"path": "/customer",
"queryParams": { "phone": "{{phone}}" },
"description": "Diz se o telefone já tem cadastro e o nome da pessoa.",
"whenToUse": "No início do atendimento, para saber se é cliente novo ou de volta.",
"responseDescription": "Se está cadastrado, o nome; e se o e-mail ainda não foi informado.",
"parameters": [
{ "name": "phone", "type": "string", "required": true,
"description": "Telefone do cliente com código do país",
"howToObtain": "É o número de quem está conversando no WhatsApp",
"example": "5511987654321" }
],
"enabled": true
},
{
"name": "criar_agendamento",
"method": "POST",
"path": "/booking",
"bodyTemplate": "{\"customerId\": \"{{customerId}}\", \"serviceId\": \"{{serviceId}}\", \"hotelId\": \"{{hotelId}}\", \"when\": \"{{when}}\"}",
"description": "Cria o agendamento e o coloca na fila do sistema.",
"whenToUse": "Só quando já souber: quem é o cliente, qual serviço, em qual local e quando.",
"responseDescription": "O número do pedido e o valor.",
"parameters": [
{ "name": "customerId", "type": "string", "required": true,
"description": "Id do cliente no sistema",
"howToObtain": "Vem de verificar_cliente", "example": "6" }
],
"enabled": true
}
/* consultar_servicos · consultar_locais · verificar_disponibilidade
solicitar_codigo · confirmar_codigo — no arquivo */
]
} } },
{ "id": "end-1", "type": "end", "data": { "label": "Fim" } }
],
"edges": [
{ "source": "start", "target": "agent-1" },
{ "source": "rag-1", "target": "agent-1", "targetHandle": "slot-1" },
{ "source": "webhook-1", "target": "agent-1", "targetHandle": "slot-2", "sourceHandle": "tool" },
{ "source": "agent-1", "target": "end-1" }
]
}
}
}| Card | Why it's here | What it does |
|---|---|---|
**Agent attendant** | One agent, many tools. | No router needed: the model itself chooses among the seven routes and the base. The prompt lists the tools and says **when** to use each one. |
| **Knowledge (RAG)** | What doesn't change. | Service area, location types, how the service works. top_k: 4 and min_score: 0.3 — minimal and relevant, to avoid inflating context. |
| **Webhook** (7 routes) | What only your system knows. | Each route becomes a tool: query services, query locations, verify customer, check availability, request code, confirm code, create scheduling. |
| Route | Method | Role in the service |
|---|---|---|
query_services | GET | Price and duration come from the system, never from the model's memory. It's the route that prevents the costliest error. |
query_locations | GET | Returns location IDs. The agent can't guess an ID — and scheduling requires one. |
verify_customer | GET + query | Right at the start: known customer is greeted by name; new one is registered without hassle. |
check_availability | GET + query | Before talking about time. It's what backs up the honesty of "it may take up to 30 minutes". |
request_code | POST | When the person says they are already a customer but the channel is not recognized: 6-digit code via email. |
confirm_code | POST | Links the channel to the account permanently — and the whenToUse says never to ask again after that. |
create_appointment | POST + body | The actual action. Ten parameters, and the whenToUse lists the four things that need to be known beforehand. |
The routes depend on each other — create_appointment needs the customerId that comes from verify_customer, and the serviceId that comes from list_services. Since the runtime doesn't yet use the dependsOn field, the order is taught in text, in the place where the model reads:
{ "name": "customerId", "howToObtain": "Comes from verify_customer", "example": "6" }It's simple and works better than it looks: the howToObtain goes into the parameter description, and the model learns to fetch the data before attempting the write.
- Replace the
baseUrlwith your API's and paste the token inauth.token(it appears masked in the file on purpose). - Rewrite the routes with your system's paths and parameters — keeping the pattern: short
description,whenToUseas a rule,howToObtainpointing to the previous route. - Point the knowledge base to yours (the
rag_idscomes empty: bases don't cross environments). - Rewrite the prompt with your company's name and tone — the structure (how it speaks / what it never does / where information comes from / how to conduct) works for any operation.
- Publish and test in sandbox before connecting the real channel.
Complete card reference
Substitution rules for {{parameters}}, authentication, errors, and what the model sees from each route are on the Webhook page.

