Melious
Tools

Tools

List, inspect, and run Melious-hosted tools — web search, URL scraping, code execution, document conversion — over REST

Tools are server-side capabilities you call over REST — web search, URL scraping, code execution, image generation, and a handful of utility tools. You run them directly, or hand their definitions to a chat model and let it decide when to call them.

Base path: /v1/tools Auth: Bearer token or x-api-key. Requires scope kit.tools. (Document conversion is its own endpoint with its own scope — see Document conversion.)

Two ways to use a tool

Call it yourself. Hit POST /v1/tools/{slug}/execute with the parameters and read the result. This is the path when your own code decides what to run.

Let a model call it. Fetch the tool definitions in OpenAI function format from GET /v1/tools/openai, pass them to Chat completions, and run whichever ones the model asks for. The model picks; you execute.

The second path is the usual one for agents. It's the standard function-calling loop from Tool calling, with the function bodies living on our side instead of yours.

Endpoints

MethodPathWhat it does
GET/v1/toolsList available tools
GET/v1/tools/openaiThe same tools as OpenAI function definitions
GET/v1/tools/{slug}One tool's metadata
GET/v1/tools/{slug}/schemaOne tool's parameter JSON Schema
POST/v1/tools/{slug}/executeRun a tool
GET/v1/tools/{slug}/rate-limitCurrent rate-limit state for a tool

List tools

GET /v1/tools

Returns the tools your key can run, paginated.

Query paramTypeDefaultDescription
pageinteger1Page number.
page_sizeinteger50Items per page, max 100.
sourcestringallFilter by native, managed, or remote.
tool_typestringallFilter by handler, mcp, or api.
categorystringallFilter by category (e.g. search).
searchstringnoneFree-text match against name and description.
{
  "items": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "web_search",
      "slug": "web-search",
      "source": "native",
      "tool_type": "handler",
      "display_name": "Web Search",
      "description": "Search the web for current information",
      "category": "search",
      "icon": "search",
      "parameters_schema": {
        "type": "object",
        "properties": {
          "query": { "type": "string", "description": "Search query" },
          "max_results": { "type": "integer", "minimum": 1, "maximum": 10, "default": 5 },
          "timeframe": { "type": "string", "enum": ["day", "week", "month", "year", "all"], "default": "all" },
          "language": { "type": "string", "default": "en" },
          "detailed": { "type": "boolean", "default": false }
        },
        "required": ["query"]
      },
      "supports_streaming": false,
      "cost_per_call": "0.004"
    }
  ],
  "total": 9,
  "page": 1,
  "page_size": 50,
  "total_pages": 1
}

name is the machine identifier (snake_case) — the human-readable label is display_name. source tells you where a tool comes from: native is built into Melious, managed is an integration we operate, remote is one you configured. tool_type tells you how it runs: handler is native code, mcp is a Model Context Protocol backend, api is an external HTTP call.

Today every published tool is native + handler. The managed/remote/mcp/api values remain in the enum for future use, but no such tools are currently live.

Get a tool's details and schema

GET /v1/tools/{slug}
GET /v1/tools/{slug}/schema

The first returns the full metadata object (same shape as a list entry). The second returns just the parameters_schema — the JSON Schema your execute call has to satisfy. Fetch the schema before executing if you're building the request dynamically.

curl https://api.melious.ai/v1/tools/web-search/schema \
  -H "Authorization: Bearer sk-mel-<YOUR_API_KEY>"

Execute a tool

POST /v1/tools/{slug}/execute

Run the tool. Pass arguments under parameters (a bare top-level object works too):

import httpx

response = httpx.post(
    "https://api.melious.ai/v1/tools/web-search/execute",
    headers={"Authorization": "Bearer sk-mel-<YOUR_API_KEY>"},
    json={"parameters": {"query": "Hanseatic League history", "max_results": 5}},
).json()

print(response["result"])
const response = await fetch(
  "https://api.melious.ai/v1/tools/web-search/execute",
  {
    method: "POST",
    headers: {
      "Authorization": "Bearer sk-mel-<YOUR_API_KEY>",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      parameters: { query: "Hanseatic League history", max_results: 5 },
    }),
  },
).then((r) => r.json());

console.log(response.result);
curl https://api.melious.ai/v1/tools/web-search/execute \
  -H "Authorization: Bearer sk-mel-<YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"parameters": {"query": "Hanseatic League history", "max_results": 5}}'

The response wraps the result with execution metadata:

{
  "success": true,
  "status": "success",
  "result": [
    { "title": "The Hanseatic League", "url": "https://...", "content": "..." }
  ],
  "error": null,
  "execution_time_ms": 1250
}
FieldTypeDescription
successbooleanWhether the run succeeded. Check this before reading result.
statusstringsuccess, error, or timeout.
resultarray | objectTool-specific output. Shape varies per tool — search and scraping return an array of results, each with title, url, and content.
errorstringHuman-readable message when success is false, otherwise null.
execution_time_msintegerWall-clock time the tool took.

Use tools with chat completions

To let a model call these tools, fetch their OpenAI function definitions and pass them straight into Chat completions:

GET /v1/tools/openai
{
  "object": "list",
  "data": [
    {
      "slug": "web-search",
      "type": "function",
      "function": {
        "name": "web_search",
        "description": "Search the web for current information",
        "parameters": {
          "type": "object",
          "properties": { "query": { "type": "string" } },
          "required": ["query"]
        }
      }
    }
  ],
  "total": 9,
  "page": 1,
  "page_size": 50,
  "usage_hint": "Pass tool slugs in the 'tools' array of /v1/chat/completions"
}

Each entry carries both the function definition (what the model reads) and the slug (what you execute). The loop:

  1. Pass the function objects in the tools array of a chat request.
  2. When the model returns a tool_calls entry, map its function.name back to the matching slug.
  3. Run POST /v1/tools/{slug}/execute with the model's arguments.
  4. Feed the result back as a tool message and continue.

The full loop, with code, is in Tool calling. The only Melious-specific step is mapping the function name to a slug and calling execute — everything else is the standard OpenAI flow.

Available tools

What we run today. The live list — with current per-call costs and parameter schemas — is GET /v1/tools.

ToolSlugCategoryWhat it does
Web searchweb-searchsearchSearch the web for current information.
URL scraperscrape-urldataFetch a URL and return its content as Markdown.
Code executioncode-executioncodeExecute Python 3.12 in a sandboxed environment.
Image generationimage-generationmediaGenerate images from text descriptions.
Knowledge searchsearch-knowledgesearchSemantic search over attached knowledge bases.
Load skillload-skillutilityLoad a skill from the user's library.
Read skill documentread-skill-documentutilityRead a document from a loaded skill.
Describe imagesdescribe-imagesmultimodalityDescribe attached images with a vision model.
Transcribe audiotranscribe-audiomultimodalityTranscribe attached audio files.

Per-call pricing: web-search €0.004, scrape-url €0.002, code-execution €0.004. The rest are free at the per-call level (image generation is billed by the underlying model instead).

Document conversion (POST /v1/documents/convert) is documented separately — it takes file uploads rather than JSON arguments, so it doesn't share the execute shape.

Rate limits

GET /v1/tools/{slug}/rate-limit

Tools are rate-limited per tool, separately from the inference rate limit. Check the current state before a heavy run:

{
  "remaining_minute": 30,
  "remaining_day": 500,
  "limit_minute": 30,
  "limit_day": 500
}

Limits vary per tool (the example above is web-search). Values count down in the current window; when either hits zero the tool is rate-limited.

Exceeding a limit returns KIT_6053 (execution rate-limited). Back off and retry.

Errors

A tool that runs but fails internally returns success: false with the message in error — it's a 200 with a failure body, not an HTTP error, so check the field:

{
  "success": false,
  "status": "timeout",
  "result": null,
  "error": "Tool execution timed out after 30000ms",
  "execution_time_ms": 30000
}

Parameter validation failures are different — they're rejected before execution, so they come back as HTTP errors with KIT_6054, not as a success: false body.

Endpoint-level failures use the standard {"error": {"code", "message"}} shape:

  • KIT_6001 — tool slug doesn't exist.
  • KIT_6054 — a parameter failed schema validation (e.g. max_results outside 1–10).
  • KIT_6051 — the tool ran but failed internally.
  • KIT_6053 — per-tool rate limit hit.
  • BILLING_2001 — insufficient balance for a paid tool.
  • AUTH_1015 — key is missing the kit.tools scope.

A malformed request body (unparseable JSON, missing required field) is rejected before routing with a generic gateway response — {"code": "ERROR", "message": "Invalid request. Please check your input and try again."} — instead of a specific tool code. Fix the request shape first.

Tool calling for the model-driven loop • Document conversion for file-to-Markdown • MCP for connecting protocol-native agents.

On this page