Skip to main content
A tool is a typed function an agent can call. It declares input, describes when to use it, and runs server-side code.

Prerequisites

  • A Veryfront project running locally (see Create project).
  • An agent that will call the tool, or an API route that invokes the tool directly (see Agents and API routes).
  • defineSchema is available from veryfront/schemas.

Define a tool

Create a file in tools/:
The filename becomes the tool’s ID. tools/get-weather.ts registers as getWeather.

Try a tool directly

Agents usually invoke tools, but direct execution is useful for testing and for API routes that expose a specific action:
Run the dev server and call the route:
Use this pattern to verify the tool contract before giving the tool to an agent.

How agents use tools

An explicit tool map authorizes only the selected tools and sends those schemas to the model immediately. Use tools: true for a broad authorized scope. The framework initially sends only the load_skill bootstrap schema when it is authorized, plus tool_search, then loads matching schemas for the next model step. form_input is authorized but deferred until it is needed. Omit tools to expose no project tools. Search results contain names and descriptions, not input or output schemas.
Use an explicit map such as tools: { getWeather: true } when the model needs a selected schema on its first step. Schema loading and tool authorization stay separate, and execution rechecks authorization. tool_search uses deterministic, case-insensitive matching. It treats underscores as spaces and ranks results in this order:
  1. Exact tool name.
  2. Tool name substring.
  3. Tool description substring.
  4. Input parameter description substring.
Equal-rank matches use ASCII tool-name order. Each search returns at most five matches. Results contain the tool name, description, and loading status, but no input or output schema. The search tool has no page or pagination parameter. Refine the query when the required tool is not in the first five matches. Search work is bounded to 4,096 catalog candidates. Each parameter schema is inspected iteratively with depth, node, and byte budgets, and the whole search has an aggregate schema-work budget. A malformed, cyclic, or over-budget schema cannot abort the search; that tool simply cannot match by parameter description. Name and description matching remains available for other healthy tools. The search loads schemas from the current authorized tools catalog. It also loads configured providerTools that the selected model supports. A provider-native search entry contains only its name and description. The runtime attaches the provider’s native schema on the next model step and never executes it as a local tool. The runtime reapplies the current authorization policy, configured provider tools, and model support before execution and checkpoint restoration, so a previously loaded name cannot restore a removed permission. Deferred loading works with direct provider model strings and provider API keys. Veryfront Cloud is not required for that path. Hosted durable execution uses the same framework search, but it requires the Veryfront API durable run-event contract. Before the next model step, the hosted runtime persists a private loaded-tool checkpoint. It fails the continuation if required persistence is unavailable, and it excludes the checkpoint from public messages and replay. In most projects, you can omit model and use openai/gpt-5.4-nano. Set model: "auto" when you want runtime defaults to choose local or Veryfront Cloud inference automatically. When a user asks “What’s the weather in Tokyo?”, an agent with tools: true:
  1. Sends the question with tool_search to the model.
  2. The model searches for a weather capability.
  3. The framework loads the matching authorized getWeather schema.
  4. The next model step calls getWeather({ city: "Tokyo" }).
  5. The tool returns { temperature: 22, conditions: "sunny" }.
  6. The model formats a natural language response.

Tool surfaces in agent config

Agent config separates tools by execution boundary: Use tools for functions you define in the project. Do not add provider-native tools or skill loader tools to tools. Use providerTools for provider-executed capabilities. In deferred mode, tool_search can load a configured capability when the selected model supports it:
Use mcpServers for remote MCP tools. Put remote visibility policy on the MCP server. When tools is an explicit object, also list the remote tool name in tools so the model can use it. When mcpServers is omitted, explicitly named tools that are not local are resolved from the Veryfront API MCP server if server bootstrap credentials are available. This makes a project pulled from Studio runnable locally without duplicating transport configuration.
VERYFRONT_API_URL selects the endpoint, while VERYFRONT_API_TOKEN and VERYFRONT_PROJECT_SLUG provide server-side identity. Environment variables never grant tools: only explicitly named unresolved tools are requested, and the remote tools/list response defines their schemas. Use mcpServers: [] to opt out, or declare { kind: "veryfront-api", toolPolicy: ... } to make the connection policy explicit. Direct application routes and hosted runtimes do not accept browser-supplied credentials or project identity for this server.

Tool configuration

Writing good descriptions

The description field is what the model reads to decide when to call your tool. Be specific, and use .describe() on schema fields to help the model understand what to pass:

Returning errors

Throw from execute to signal an error. The agent sees the error message and can retry or respond accordingly:

Tools with context

The execute function receives an optional second argument with runtime context:
Pass context from the API route:

Inline tools

For one-off tools that don’t need auto-discovery, define them inline:
evaluateMathExpression is your own validated math evaluator. Avoid passing free-form input into eval() or Function().

Verify it worked

Restart veryfront dev after creating the tool file. To run the tool by itself, expose a small debug API route:
A working tool returns the JSON your execute function produced. Remove the debug route before deploying.