Chapter 19: Defining Agents and Tools
TL;DR
- Define an Agent Persona with
upsert_agentonworka/orchestrator. Thedescriptionfield is the system prompt for the agent. - Define a Tool Schema (JSON‑Schema style) so the agent knows how to call your tools.
- Register the Tool with
upsert_toolto make it available to agents.
An AI workflow needs two building blocks:
- An Agent to plan and reason.
- A set of Tools the agent can call.
You define both by calling tools on the worka/orchestrator virtual pack.
Creating an Agent
Agents are LLM personas. You define them by calling upsert_agent.
Backend example (Rust, in‑process MCP):
// Pseudocode – exact SDK API may differ
let client = McpClient::inproc();
client.call(
"worka/orchestrator",
"upsert_agent",
json!({
"name": "research-agent",
"description": "You are a helpful research assistant. Summarize sources and cite them."
})
).await?;
A2UI example (via action):
{
"type": "button",
"props": {
"label": "Create Agent",
"onClick": {
"type": "worka_action",
"target": "worka/orchestrator",
"tool": "upsert_agent",
"input": {
"name": "research-agent",
"description": "You are a helpful research assistant. Summarize sources and cite them."
}
}
}
}
Defining and Registering Tools
An agent can't do anything without tools. For an agent to use a tool from your MCP server (e.g., the greet tool we built), you must first register its schema with the Orchestrator. This schema is a machine-readable description of the tool's function and parameters, which the LLM uses to understand how and when to use it.
Step 1: Define the Tool Schema
Worka uses a format based on the widely-used JSON Schema standard. You define an object that describes the parameters your tool's function accepts.
Let's imagine we have a tool named google_search that takes a single string parameter, query.
const googleSearchSchema = {
type: 'object', // The root is always an object
properties: {
query: { // The name of the parameter
type: 'string',
description: 'The search query to send to Google.' // A description for the LLM
}
},
required: ['query'] // An array of required parameter names
};
Step 2: Register the Schema with upsert_tool
Once you have the schema, you call the upsert_tool tool on the worka/orchestrator pack. This tells the Orchestrator that this tool exists and makes it available to your agents.
Backend example (Rust):
let client = McpClient::inproc();
client.call(
"worka/orchestrator",
"upsert_tool",
json!({
"name": "google_search",
"description": "Performs a Google search and returns top results.",
"schema": googleSearchSchema
})
).await?;
By separating the tool's implementation (in your MCP server) from its registration (via upsert_tool), the system remains decoupled. The Orchestrator doesn't need to know how your tool works, only what it does and what parameters it needs. When an agent decides to use google_search, the Orchestrator will see the tool call and route it to your pack's MCP server for execution.