diff --git a/agent/README.md b/agent/README.md
index 588670fe..676097fc 100644
--- a/agent/README.md
+++ b/agent/README.md
@@ -78,7 +78,87 @@ yao agent test -i "Hello, how are you?"
yao start
```
-Access via API: `POST /api/__yao/agent`
+Access via API: `POST /v1/chat/completions`
+
+## Examples
+
+### Hook: Route to Specialist
+
+```typescript
+// src/index.ts
+function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create {
+ const last = messages[messages.length - 1]?.content || "";
+ if (last.includes("refund")) {
+ return { delegate: { agent_id: "refund-specialist", messages } };
+ }
+ return null;
+}
+```
+
+### Database Query
+
+```json
+// package.yao - Enable auto DB search
+{ "db": { "models": ["orders", "products"] } }
+```
+
+```bash
+# Test: Agent auto-generates QueryDSL and searches database
+yao agent test -i "Find orders over $1000 from last month"
+```
+
+### MCP Tools (Process Transport)
+
+```json
+// mcps/tools.mcp.yao - Define MCP server with Yao Processes
+{
+ "label": "Tools",
+ "transport": "process",
+ "tools": {
+ "search_orders": "models.order.Paginate",
+ "create_order": "models.order.Create"
+ }
+}
+```
+
+```json
+// mcps/mapping/tools/schemes/search_orders.in.yao - Input schema
+{
+ "type": "object",
+ "properties": {
+ "keyword": { "type": "string" },
+ "page": { "type": "integer" }
+ },
+ "x-process-args": [":arguments"]
+}
+```
+
+```json
+// package.yao
+{ "mcp": { "servers": [{ "server_id": "tools" }] } }
+```
+
+### Sidebar Page (Display Data)
+
+Pages render in the right sidebar during conversation to display structured data:
+
+```html
+
+
+
{{ title }}
+
+
+ | {{ row.name }} |
+ {{ row.value }} |
+
+
+
+```
+
+```bash
+yao sui build agent # Build pages
+# Rendered via ctx.Send({ type: "page", props: { page: "result", data: {...} } })
+```
## Documentation
@@ -88,6 +168,7 @@ Access via API: `POST /api/__yao/agent`
- [Context API](docs/context-api.md) - Messaging, memory, trace, MCP
- [MCP Integration](docs/mcp.md) - Tool servers and resources
- [Search](docs/search.md) - Web, knowledge base, and database search
+- [Pages](docs/pages.md) - Web UI for agents (SUI framework)
- [Internationalization](docs/i18n.md) - Multi-language support
- [Testing](docs/testing.md) - Agent testing framework
@@ -136,13 +217,19 @@ flowchart LR
## API Endpoints
-| Endpoint | Method | Description |
-| ------------------------------- | ------ | ------------------- |
-| `/api/__yao/agent` | POST | Chat with assistant |
-| `/api/__yao/agent/history` | GET | Get chat history |
-| `/api/__yao/agent/chats` | GET | List chat sessions |
-| `/api/__yao/agent/assistants` | GET | List assistants |
-| `/api/__yao/agent/upload/:type` | POST | Upload files |
+OpenAPI endpoints (base URL: `/v1`):
+
+| Endpoint | Method | Description |
+| -------------------------------------- | ------ | --------------------- |
+| `/v1/chat/completions` | POST | Chat with assistant |
+| `/v1/chat/sessions` | GET | List chat sessions |
+| `/v1/chat/sessions/:chat_id` | GET | Get chat session |
+| `/v1/chat/sessions/:chat_id/messages` | GET | Get messages |
+| `/v1/agent/assistants` | GET | List assistants |
+| `/v1/agent/assistants/:id` | GET | Get assistant details |
+| `/v1/file/:uploaderID` | POST | Upload files |
+| `/v1/file/:uploaderID/:fileID` | GET | Get file info |
+| `/v1/file/:uploaderID/:fileID/content` | GET | Download file |
## License
diff --git a/agent/docs/mcp.md b/agent/docs/mcp.md
index 5b030384..5ed0914e 100644
--- a/agent/docs/mcp.md
+++ b/agent/docs/mcp.md
@@ -8,40 +8,43 @@ Create `mcps/tools.mcp.yao` in the assistant directory:
```json
{
- "name": "Tools",
+ "label": "Tools",
"description": "Custom tools for the assistant",
"transport": "process",
- "process": {
- "command": "node",
- "args": ["server.js"]
+ "tools": {
+ "search": "scripts.tools.Search",
+ "create": "models.data.Create"
}
}
```
### Transport Types
-**Process (Local)**
+**Process (Yao Internal)**
+
+Map Yao Processes directly to MCP tools:
```json
{
"transport": "process",
- "process": {
- "command": "python",
- "args": ["mcp_server.py"],
- "env": { "API_KEY": "$ENV.API_KEY" }
+ "tools": {
+ "search": "models.data.Paginate",
+ "create": "models.data.Create"
+ },
+ "resources": {
+ "detail": "models.data.Find"
}
}
```
-**HTTP**
+**STDIO (Local Server)**
```json
{
- "transport": "http",
- "http": {
- "url": "https://mcp.example.com",
- "headers": { "Authorization": "Bearer $ENV.TOKEN" }
- }
+ "transport": "stdio",
+ "command": "python",
+ "arguments": ["mcp_server.py"],
+ "env": { "API_KEY": "$ENV.API_KEY" }
}
```
@@ -50,9 +53,8 @@ Create `mcps/tools.mcp.yao` in the assistant directory:
```json
{
"transport": "sse",
- "sse": {
- "url": "https://mcp.example.com/events"
- }
+ "url": "https://mcp.example.com/events",
+ "authorization_token": "$ENV.TOKEN"
}
```
@@ -159,27 +161,37 @@ const prompts = ctx.mcp.ListPrompts("server-id");
const prompt = ctx.mcp.GetPrompt("server-id", "system", { role: "helper" });
```
-## Tool Mapping
+## Tool Schema Mapping
-Map MCP tools to Yao processes:
+Define input schemas for process transport tools:
```
mcps/
└── mapping/
- └── tools/
- ├── search.yao
- └── calculate.yao
+ └── /
+ └── schemes/
+ ├── search.in.yao # Input schema
+ └── search.out.yao # Output schema (optional)
```
-**mapping/tools/search.yao**
+**mapping/tools/schemes/search.in.yao**
```json
{
- "process": "scripts.search.Execute",
- "args": ["{{input}}"]
+ "type": "object",
+ "description": "Search data",
+ "properties": {
+ "keyword": { "type": "string" },
+ "page": { "type": "integer" }
+ },
+ "x-process-args": [":arguments"]
}
```
+The `x-process-args` maps MCP arguments to Yao Process parameters:
+- `":arguments"` - Pass entire arguments object
+- `"$args.field"` - Extract specific field
+
## Error Handling
```typescript
@@ -208,12 +220,12 @@ function Next(ctx: agent.Context, payload: agent.Payload): agent.Next {
```json
{
- "name": "Calculator",
+ "label": "Calculator",
"description": "Math operations",
"transport": "process",
- "process": {
- "command": "node",
- "args": ["calc-server.js"]
+ "tools": {
+ "add": "scripts.math.Add",
+ "multiply": "scripts.math.Multiply"
}
}
```
@@ -226,7 +238,7 @@ function Next(ctx: agent.Context, payload: agent.Payload): agent.Next {
"connector": "gpt-4o",
"mcp": {
"servers": [
- { "server_id": "agents.assistant.calculator", "tools": ["add", "multiply"] }
+ { "server_id": "calculator", "tools": ["add", "multiply"] }
]
}
}
@@ -242,7 +254,7 @@ function Create(ctx: agent.Context, messages: agent.Message[]): agent.Create {
// Enable calculator
return {
messages,
- mcp_servers: [{ server_id: "agents.assistant.calculator" }]
+ mcp_servers: [{ server_id: "calculator" }]
};
}
return { messages };
@@ -252,7 +264,7 @@ function Next(ctx: agent.Context, payload: agent.Payload): agent.Next {
const { tools } = payload;
if (tools?.length > 0) {
- const calcResult = tools.find(t => t.server.includes("calculator"));
+ const calcResult = tools.find(t => t.server === "calculator");
if (calcResult?.result) {
return {
data: {
diff --git a/agent/docs/pages.md b/agent/docs/pages.md
new file mode 100644
index 00000000..a497b26f
--- /dev/null
+++ b/agent/docs/pages.md
@@ -0,0 +1,324 @@
+# Agent Pages
+
+Agent Pages provide a built-in SUI (Simple User Interface) framework for building web interfaces for AI agents. Pages are automatically loaded from the `/agent/template/` directory for global templates and `/assistants//pages/` for individual assistant pages.
+
+## Directory Structure
+
+```
+/
+├── agent/
+│ └── template/ # Global template directory
+│ ├── __document.html # Document template
+│ ├── __data.json # Global data
+│ ├── __assets/ # Global assets
+│ │ ├── css/
+│ │ ├── js/
+│ │ └── images/
+│ ├── pages/ # Global pages (login, error, etc.)
+│ │ └── login/
+│ │ └── login.html
+│ └── __locales/ # Internationalization
+│
+└── assistants/
+ └── my-assistant/
+ ├── package.yao
+ └── pages/ # Assistant-specific pages
+ ├── index/
+ │ ├── index.html
+ │ ├── index.css
+ │ ├── index.ts
+ │ └── index.backend.ts
+ └── __assets/ # Optional assistant assets
+```
+
+## Route Mapping
+
+| File Path | Public URL |
+|-----------|------------|
+| `/agent/template/pages/login/login.html` | `/agents/login` |
+| `/assistants/demo/pages/index/index.html` | `/agents/demo/index` |
+| `/assistants/demo/pages/chat/chat.html` | `/agents/demo/chat` |
+
+## Quick Start
+
+### 1. Create Document Template
+
+**`/agent/template/__document.html`**:
+
+```html
+
+
+
+
+ {{ $global.title }}
+
+
+
+
+ {{ __page }}
+
+
+```
+
+### 2. Create Global Data
+
+**`/agent/template/__data.json`**:
+
+```json
+{
+ "title": "AI Agent",
+ "version": "1.0.0"
+}
+```
+
+### 3. Create a Page
+
+**`/assistants/my-assistant/pages/index/index.html`**:
+
+```html
+
+```
+
+**`/assistants/my-assistant/pages/index/index.json`**:
+
+```json
+{
+ "title": "Chat",
+ "messages": []
+}
+```
+
+**`/assistants/my-assistant/pages/index/index.css`**:
+
+```css
+.page {
+ max-width: 800px;
+ margin: 0 auto;
+ padding: 24px;
+}
+
+.messages {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.message.user {
+ align-self: flex-end;
+ background: #007bff;
+ color: white;
+}
+
+.message.assistant {
+ align-self: flex-start;
+ background: #f0f0f0;
+}
+```
+
+### 4. Add Backend Script
+
+**`/assistants/my-assistant/pages/index/index.backend.ts`**:
+
+```typescript
+function BeforeRender(request: Request): Record {
+ const chatId = request.query.chat_id;
+ return {
+ messages: chatId ? Process("scripts.chat.GetHistory", chatId) : [],
+ user: request.authorized?.user_id
+ };
+}
+
+function ApiGetData(request: Request): any {
+ const { id } = request.payload;
+ return Process("models.data.Find", id, {});
+}
+```
+
+### 5. Add Frontend Script
+
+**`/assistants/my-assistant/pages/index/index.ts`**:
+
+```typescript
+function index(component: HTMLElement) {
+ this.root = component;
+ this.store = new __sui_store(component);
+
+ this.handleClick = async (event: Event) => {
+ const data = await this.backend.ApiGetData({ id: 1 });
+ console.log(data);
+ };
+}
+```
+
+### 6. Build and Run
+
+```bash
+# Build pages
+yao sui build agent
+
+# Or watch for changes
+yao sui watch agent
+
+# Start server
+yao start
+```
+
+Access at: `http://localhost:5099/agents/my-assistant/index`
+
+## Template Syntax
+
+### Data Binding
+
+```html
+
+{{ title }}
+
+
+{{ user.name }}
+
+
+{{ description || "No description" }}
+```
+
+### Conditionals
+
+```html
+Welcome, {{ user.name }}!
+Welcome, Guest!
+Please log in
+```
+
+### Loops
+
+```html
+
+ -
+ {{ i + 1 }}. {{ item.name }}
+
+
+```
+
+### Events
+
+```html
+
+
+```
+
+### Components
+
+Pages can use other pages as components:
+
+```html
+
+
+
+
+
+ Content
+
+
+```
+
+## Built-in Variables
+
+| Variable | Description |
+|----------|-------------|
+| `$global` | Global data from `__data.json` |
+| `$query` | URL query parameters |
+| `$param` | URL path parameters |
+| `$payload` | POST request body |
+| `$cookie` | Cookie values |
+| `$url` | Current URL info |
+| `$theme` | Current theme |
+| `$locale` | Current locale |
+| `$auth` | OAuth authorization info (if authenticated) |
+
+## Page Configuration
+
+Create `.config` for page settings:
+
+```json
+{
+ "title": "Page Title",
+ "guard": "bearer-jwt",
+ "cache": 3600,
+ "data": {
+ "key": "value"
+ }
+}
+```
+
+## Asset Paths
+
+- **Global assets**: `/agents/assets/...` → `/agent/template/__assets/...`
+- **Assistant assets**: `/agents//assets/...` → `/assistants//pages/__assets/...`
+
+## Build Output
+
+```
+/public/agents/
+├── assets/
+│ ├── libsui.min.js # SUI frontend SDK
+│ ├── css/ # Global CSS
+│ ├── js/ # Global JS
+│ └── images/ # Global images
+│
+├── login.sui # Global page
+├── login.cfg
+│
+└── my-assistant/
+ ├── index.sui # Assistant page
+ └── index.cfg
+```
+
+## Authentication
+
+Pages default to public access. To require authentication:
+
+**`/assistants/my-assistant/pages/dashboard/dashboard.config`**:
+
+```json
+{
+ "guard": "bearer-jwt"
+}
+```
+
+Available guards:
+
+| Guard | Description |
+|-------|-------------|
+| `-` | No authentication (default) |
+| `bearer-jwt` | JWT token in Authorization header |
+| `cookie-jwt` | JWT token in cookie |
+| `oauth` | OAuth 2.0 authentication |
+
+## Frontend API
+
+The SUI frontend SDK provides:
+
+```typescript
+// Backend calls
+const data = await this.backend.ApiMethodName(payload);
+
+// State management
+this.store.Set("key", value);
+const value = this.store.Get("key");
+
+// OpenAPI client (if using oauth guard)
+const response = await OpenAPI.Get("/api/endpoint");
+await OpenAPI.Post("/api/endpoint", data);
+```
+
+## Related Documentation
+
+- [SUI Template Syntax](../../sui/docs/template-syntax.md)
+- [SUI Data Binding](../../sui/docs/data-binding.md)
+- [SUI Components](../../sui/docs/components.md)
+- [SUI Frontend API](../../sui/docs/frontend-api.md)