Skip to main content

Chat Server (HTTP API)

Wunderland ships a built-in HTTP server that exposes your agent as a REST API. Start it, send a POST request, get a response. No SDK required.

Quick Start

1. Create an agent

wunderland init my-agent
cd my-agent
warning

You must cd into the agent directory before running wunderland start. The server reads agent.config.json from the current working directory.

2. Start the server

wunderland start

Output:

  Wunderland v1.x.x
Agent: my-agent
Provider: ollama (llama3.1:8b)

Health: http://localhost:3777/health
Chat: POST http://localhost:3777/chat
HITL: http://localhost:3777/hitl

3. Send a message

curl -X POST http://localhost:3777/chat \
-H "Content-Type: application/json" \
-d '{"message": "Create a file with the two richest men in history"}'

The agent processes your message, runs any tools it needs (file creation, web search, etc.), and returns the result.

POST /chat

The main endpoint. Send a JSON body, get the agent's response.

Request

POST /chat
Content-Type: application/json

Required fields:

FieldTypeDescription
messagestringThe prompt to send to the agent

Optional fields:

FieldTypeDefaultDescription
sessionIdstring"default"Conversation session ID. Messages within the same session share context (up to 200 messages).
tenantIdstringTenant identifier for multi-tenant deployments
toolFailureModestringHow to handle tool failures ("continue", "abort", etc.)
resetbooleanfalseClear the session history before processing this message

Examples

Simple message:

{
"message": "What is the capital of France?"
}

With session tracking:

{
"message": "Now tell me about its history",
"sessionId": "user-42"
}

Messages with the same sessionId share conversation history. The agent remembers previous messages in the session, so follow-up questions work naturally.

Reset a session:

{
"message": "Let's start fresh",
"sessionId": "user-42",
"reset": true
}

Response

{
"reply": "The capital of France is Paris.",
"toolCalls": 0,
"fallback": false
}
FieldTypeDescription
replystringThe agent's text response
toolCallsnumberNumber of tool calls executed during this turn
fallbackbooleanWhether a fallback provider was used

Error Responses

StatusBodyCause
400{"error": "Missing \"message\" in JSON body."}Empty or missing message field
401{"error": "Unauthorized"}Invalid or missing chat secret (when configured)
500{"error": "..."}LLM or tool execution failure

GET /chat

Returns usage instructions for the endpoint:

curl http://localhost:3777/chat
{
"endpoint": "POST /chat",
"usage": "Send a JSON body with { \"message\": \"your prompt\" }",
"example": "curl -X POST http://localhost:3777/chat -H \"Content-Type: application/json\" -d '{\"message\":\"hello\"}'"
}

Other Endpoints

EndpointMethodDescription
/healthGETHealth check (returns {"status":"ok"})
/chatPOSTSend a message to the agent
/hitlGETHuman-in-the-loop approval web UI
/hitl/pendingGETList pending approval requests
/hitl/streamGETSSE stream of approval events
/pairingGETAgent pairing interface

Server Options

wunderland start --port 4000 --host 127.0.0.1
FlagDefaultDescription
--port <number>3777Server port
--host <address>0.0.0.0Bind address
--no-webchatDisable the built-in WebChat UI
--detachRun in the background
--auto-approve-toolsSkip tool approval prompts (autonomous mode)

Authentication

By default, the chat endpoint is open (no auth required). To secure it, set a chat secret:

Environment variable:

export WUNDERLAND_CHAT_SECRET=my-secret-token
wunderland start

Or in agent.config.json:

{
"chat": {
"secret": "my-secret-token"
}
}

Then include the secret in requests:

# Via header
curl -X POST http://localhost:3777/chat \
-H "Content-Type: application/json" \
-H "x-wunderland-chat-secret: my-secret-token" \
-d '{"message": "hello"}'

# Or via query parameter
curl -X POST "http://localhost:3777/chat?secret=my-secret-token" \
-H "Content-Type: application/json" \
-d '{"message": "hello"}'

Using from Code

JavaScript / TypeScript

const response = await fetch('http://localhost:3777/chat', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: 'Hello, what can you do?' }),
});

const data = await response.json();
console.log(data.reply);

Python

import requests

response = requests.post('http://localhost:3777/chat', json={
'message': 'Hello, what can you do?'
})

data = response.json()
print(data['reply'])

Session Management

The server maintains conversation history per sessionId in memory.

  • Default session ID is "default" if not specified
  • Sessions are capped at 200 messages (oldest messages are trimmed, system prompt is preserved)
  • Sessions are lost when the server restarts
  • Send "reset": true to clear a session

For persistent conversation history, use the terminal chat (wunderland chat) or connect a channel adapter (Discord, Telegram, etc.).