diff --git a/.github/workflows/api-lint.yml b/.github/workflows/api-lint.yml new file mode 100644 index 0000000..d884b28 --- /dev/null +++ b/.github/workflows/api-lint.yml @@ -0,0 +1,16 @@ +name: API linting + +on: [pull_request] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Set up node + uses: actions/setup-node@v4 + - name: Install Redocly CLI + run: npm install -g @redocly/cli@latest + - name: Run linting + run: redocly lint "specification/**/openapi.json" --format=github-actions diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d01fca5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +package-lock.json +pnpm-lock.yaml diff --git a/.redocly.lint-ignore.yaml b/.redocly.lint-ignore.yaml new file mode 100644 index 0000000..f86e5d9 --- /dev/null +++ b/.redocly.lint-ignore.yaml @@ -0,0 +1,8 @@ +# This file instructs Redocly's linter to ignore the rules contained for specific parts of your API. +# See https://redocly.com/docs/cli/ for more information. +specification/http/1.0/openapi.json: + no-empty-servers: + - '#/openapi' + operation-4xx-response: + - '#/paths/~1health/get/responses' + - '#/paths/~1tools/get/responses' diff --git a/RFC.md b/RFC.md index 4341597..af7b62c 100644 --- a/RFC.md +++ b/RFC.md @@ -4,248 +4,1019 @@ ## Abstract -This document specifies the Open Tool Calling Standard, a comprehensive communication layer for agents calling tools. It defines the structures and protocols used to describe tools, initiate tool calls, and process responses. The standard is based on a set of JSON schemas that govern tool definitions, tool requests, and tool responses. It aims to provide a unified, extensible, and interoperable framework for agent-to-tool interactions. +This document specifies the Open Tool Calling (OTC) standard, a comprehensive communication protocol for AI agents (clients) calling tools. It defines the structures and protocols used to describe tools, initiate tool calls, and process responses. The standard is comprised of JSON and OpenAPI schemas that govern tool definitions, tool requests, and tool responses. It aims to provide a unified, extensible, and interoperable framework for client-to-tool interactions. + +The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [BCP 14](https://datatracker.ietf.org/doc/html/bcp14) [[RFC2119]](https://datatracker.ietf.org/doc/html/rfc2119) [[RFC8174]](https://datatracker.ietf.org/doc/html/rfc8174) when, and only when, they appear in all capitals, as shown here. + +## Editors + +- Nate Barbettini ([@nbarbettini](https://github.com/nbarbettini)) +- Eugene Yurtsev ([@eyurtsev](https://github.com/eyurtsev)) +- Sam Partee ([@spartee](https://github.com/spartee)) --- ## Table of Contents -1. [Introduction](#introduction) -2. [Terminology](#terminology) -3. [Architecture Overview](#architecture-overview) -4. [Schema Definitions](#schema-definitions) - - [Tool Definition Schema](#tool-definition-schema) - - [Tool Request Schema](#tool-request-schema) - - [Tool Response Schema](#tool-response-schema) -5. [Communication Flow](#communication-flow) -6. [Security and Authorization](#security-and-authorization) -7. [Extensibility and Versioning](#extensibility-and-versioning) -8. [Conclusion](#conclusion) -9. [References](#references) +1. [Introduction](#1-introduction) +2. [Terminology](#2-terminology) +3. [Architecture Overview](#3-architecture-overview) +4. [Schema Definitions](#4-schema-definitions) + - [Tool Definition Schema](#41-tool-definition-schema) + - [Tool Request Schema](#42-tool-request-schema) + - [Tool Response Schema](#43-tool-response-schema) +5. [Communication Flows](#5-communication-flows) +6. [Security and Authorization](#6-security-and-authorization) +7. [Extensibility and Versioning](#7-extensibility-and-versioning) +8. [Conclusion](#8-conclusion) +9. [References](#9-references) --- ## 1. Introduction -The Open Tool Calling Standard establishes a set of protocols and formats to facilitate communication between agents (clients) and tools (services) in distributed systems. It ensures that tool definitions, requests, and responses adhere to a structured and open standard. This RFC presents detailed JSON schema specifications that serve as the backbone for this standard, enabling uniform interpretation and execution of tool interactions. - ---- +The Open Tool Calling standard establishes a set of protocols and formats to facilitate communication between agents (clients) and tools (functions or services) in distributed systems. It ensures that tool definitions, requests, and responses adhere to a structured and open standard. This specification presents detailed JSON and OpenAPI schemas that serve as the backbone for this standard, enabling uniform interpretation and execution of tool interactions. ## 2. Terminology -- **Agent:** An entity that issues requests to tools for performing specific tasks. -- **Tool:** A service or function that can be invoked by an agent using the defined protocols. -- **Schema:** A formal description of the data structure, typically expressed in JSON Schema, used to validate data formats. -- **RFC:** Request for Comments; a document that describes methods, behaviors, research, or innovations applicable to the Internet. -- **Toolkit:** A collection of tools grouped under a common framework and versioned accordingly. -- **JSON Schema:** A vocabulary that allows you to annotate and validate JSON documents. - ---- +- **Client:** An entity that issues requests to tools for performing specific tasks. +- **Server** (or Tool Server): An entity that hosts a collection of tools and processes tool calls. +- **Tool:** A service or function that can be executed (called) by a client using the defined protocols. ## 3. Architecture Overview -The Open Tool Calling Standard is designed around three key components: +The Open Tool Calling standard is designed around three key components: -1. **Tool Definition:** A schema that specifies how a tool is described. It includes metadata such as the tool's name, fully qualified name, toolkit information, and the input/output specifications. -2. **Tool Request:** A schema that details the structure of a tool call. It encompasses the run identifier, execution context, tool metadata, and input parameters. -3. **Tool Response:** A schema that outlines the structure of the response returned after a tool execution. It provides details on execution status, duration, and the actual output (or errors) of the tool call. +1. **Tool Definition:** A schema that specifies how a tool is described. It includes metadata such as the tool's name, unique identifier, and the input/output specifications. +2. **Tool Request:** A schema that details the structure of a tool call. It encompasses the call identifier, execution context, tool metadata, and input parameters. +3. **Tool Response:** A schema that outlines the structure of the response returned from a tool call. It provides details on execution status, duration, and the actual output (or errors) of the tool call. -These components ensure consistent communication between agents and tools, regardless of the implementation details of each tool. +These components ensure consistent communication between clients and tools, regardless of the implementation details of each tool. ```mermaid sequenceDiagram - participant A as Agent - participant R as Registry + participant C as Client + participant S as Tool Server participant T as Tool - %% Tool Registration - A->>R: Submit Tool Definition (JSON Schema) - R-->>A: Acknowledge Registration + ## Health check + C->>S: Request health check + S->>C: Health check response - %% Tool Invocation - A->>T: Send Tool Request (run_id, execution_id, inputs, context) - T->>T: Validate Request & Process Execution - Note right of T: Includes authorization and secrets handling - T-->>A: Return Tool Response (success, value/error/artifact, duration) + %% Tool discovery + C->>S: Request tool list + S->>C: List of available tools - %% Post Execution - A->>R: Optionally update tool status/log (if applicable) + %% Tool call + C->>S: Send call request + Note left of C: Resolve requirements (such as authorization) + S->>T: Run tool (function) + T->>S: Return tool response + S->>C: Return tool response ``` ---- - ## 4. Schema Definitions ### 4.1 Tool Definition Schema The Tool Definition Schema establishes the properties and required fields to describe a tool. It consists of the following sections: -- **Metadata:** +#### Metadata - - **`$schema`**: URI defining the JSON Schema version. - - **`name`**: A human-readable name for the tool. - - **`fully_qualified_name`**: A unique identifier for the tool. - - **`description`**: A human-readable explanation of the tool's purpose. +- **`id`** (required): A unique identifier for the tool, in the following format: `ToolkitName.ToolName@Version`. For example, `Calculator.Add@1.0.0`. The `id` MUST be unique within the scope of the Tool Server. +- **`name`** (required): A human-readable name for the tool. For example, `Add` or `Calculator_Add`. The name MUST contain only alphanumeric characters, underscores, and dashes, and be between 1 and 64 characters in length. +- **`description`** (required): A human-readable explanation of the tool's purpose. This field SHOULD be used by both humans and AI models. +- **`version`** (required): The semantic version of the tool, e.g. `1.0.0`. Multiple versions of the same tool MAY exist. -- **Toolkit Information:** +#### Input Schema - - **`toolkit`**: Contains the toolkit’s name, description, and version. +**`input_schema`** (required): Describes the input parameters for the tool. -- **Input Schema:** +- **`parameters`** (required): A JSON Schema object that describes the input parameters for the tool. This schema supports standard JSON Schema validation but excludes `$ref` and nested definitions/schemas for simplicity. The `parameters` field MUST be present, but MAY be an empty object. - - **`input`**: Describes the parameters accepted by the tool. - - Each parameter includes: - - **`name`**: Parameter name. - - **`required`**: Boolean indicating whether the parameter is mandatory. - - **`description`**: Explanation of the parameter. - - **`value_schema`**: Data type and structure details (including support for arrays with inner type definitions). - - **`inferrable`**: (Optional) Indicates if the value can be inferred automatically. +If present, each parameter in `parameters` MUST be a valid JSON Schema object and MUST contain a `description` field describing the parameter. + +#### Output Schema + +**`output_schema`** (required): A JSON Schema object that describes the output parameters for the tool. `output_schema` MAY be an empty object indicating that the tool can return an unconstrained ("any") JSON value, and MAY be `null` indicating that the tool does not return any output. + +#### Requirements + +**`requirements`** (optional): Describes tool requirements that are not strictly input parameters, such as an API key needed to call a target API, or that a tool requires OAuth 2.0-based authorization. + +If the `requirements` field is not present, the server MUST allow the tool to be executed without passing any additional information. + +If the `requirements` field and one or more sub-fields are present, the client MUST pass the required information in the `context` field of the `CallToolRequest` schema. + +**`requirements.authorization`** (optional): Declares one or more required authorization methods. + +Each authorization method is described as an object with the following properties: + +- **`id`**: A unique identifier for the authorization method or authorization provider. +- **`oauth2`** (optional): For tools that require OAuth 2.0-based authorization, this field contains the OAuth 2.0-specific authorization details. + - **`scopes`**: A list of scopes that must be granted for the tool to execute properly. + +**`requirements.secrets`** (optional): Declares one or more secrets that are required for the tool to execute. + +Each required secret is described as an object with the following properties: + +- **`id`**: A unique identifier for the secret. + +#### Non-Normative Examples + +1. **Calculator.Add** + + A tool that adds two numbers. + + ```json + { + "id": "Calculator.Add@1.0.0", + "name": "Calculator_Add", + "description": "Adds two numbers together.", + "version": "1.0.0", + "input_schema": { + "parameters": { + "type": "object", + "properties": { + "a": { + "type": "number", + "description": "The first number to add." + }, + "b": { + "type": "number", + "description": "The second number to add." + } + }, + "required": ["a", "b"] + } + }, + "output_schema": { + "type": "number", + "description": "The sum of the two numbers." + } + } + ``` + +2. **Doorbell.Ring (No Output)** + + A tool that rings a doorbell but produces no output parameters. + + ```json + { + "id": "Doorbell.Ring@0.1.0", + "name": "Doorbell_Ring", + "description": "Rings a doorbell given a doorbell ID.", + "version": "0.1.0", + "input_schema": { + "parameters": { + "type": "object", + "properties": { + "doorbell_id": { + "type": "string", + "description": "The ID of the doorbell to ring." + } + }, + "required": ["doorbell_id"] + } + }, + "output_schema": null + } + ``` + +3. **System.GetTimestamp (No Input)** + + A tool that requires no input but produces a timestamp output. + + ```json + { + "id": "System.GetTimestamp@1.0.0", + "name": "System_GetTimestamp", + "description": "Retrieves the current system timestamp.", + "version": "1.0.0", + "input_schema": { + "parameters": { + "type": "object" + } + }, + "output_schema": { + "type": "object", + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "description": "The current system timestamp." + } + }, + "required": ["timestamp"] + } + } + ``` + +4. **Gmail.GetEmails (OAuth 2.0 Authorization)** + + A tool that retrieves emails from Gmail using OAuth 2.0 for authorization. + + ```json + { + "id": "Gmail.GetEmails@1.2.0", + "name": "Gmail_GetEmails", + "description": "Retrieves emails from Gmail using OAuth 2.0 authentication.", + "version": "1.2.0", + "input_schema": { + "parameters": { + "type": "object", + "properties": { + "query": { + "type": "string", + "description": "Search query for filtering emails." + } + }, + "required": [] + } + }, + "output_schema": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { "type": "string" }, + "subject": { "type": "string" }, + "snippet": { "type": "string" } + }, + "required": ["id", "subject", "snippet"] + }, + "description": "List of retrieved emails." + } + }, + "required": ["emails"] + }, + "requirements": { + "authorization": [ + { + "id": "google", + "oauth2": { + "scopes": ["https://www.googleapis.com/auth/gmail.readonly"] + } + } + ], + "user_id": true + } + } + ``` + +5. **SMS.Send (Secret Requirement)** + + A tool that sends SMS messages using Twilio and requires a `TWILIO_API_KEY` secret. + + ```json + { + "id": "SMS.Send@0.1.2", + "name": "SMS_Send", + "description": "Sends SMS messages using Twilio. Requires a valid TWILIO_API_KEY.", + "version": "0.1.2", + "input_schema": { + "parameters": { + "type": "object", + "properties": { + "to": { + "type": "string", + "description": "Recipient phone number." + }, + "message": { + "type": "string", + "description": "Message content to send." + } + }, + "required": ["to", "message"] + } + }, + "output_schema": { + "type": "object", + "properties": { + "status": { + "type": "string", + "description": "Status of the SMS sending operation." + } + }, + "required": ["status"] + }, + "requirements": { + "secrets": [ + { + "id": "TWILIO_API_KEY" + } + ] + } + } + ``` -- **Output Schema:** +### 4.2 Tool Request Schema - - **`output`**: Specifies the expected result of the tool execution. - - **`available_modes`**: A list of modes such as `value`, `error`, `artifact`, etc. - - **`description`**: Human-readable explanation of the output. - - **`value_schema`**: Defines the data type and structure of the output value. +The `CallToolRequest` schema is designed to encapsulate the details of a tool execution (tool call). -- **Requirements:** - - **`requirements`**: Describes authorization or secret requirements. - - **`secrets`**: Array of secret definitions. - - **`authorization`**: Specifies required authorization methods (e.g., token-based). +#### Run and Execution Identification -The complete JSON Schema ensures that every tool adheres to a well-defined structure, facilitating consistent tool registration and discovery. +- **`tool_id`**: The unique identifier of the tool to call. +- **`call_id`** (optional): A unique identifier and idempotency key for this tool call. If not provided, the server will generate one. +- **`trace_id`** (optional): Unique identifier for the trace of the tool call, if supplied by the client. ---- +#### Input Parameters -### 4.2 Tool Request Schema +- **`inputs`**: An unconstrained object containing the parameters needed by the tool. -The Tool Request Schema is designed to encapsulate the details of a tool invocation: +#### Context -- **Run and Execution Identification:** +- **`context`** (optional): Provides additional execution context, e.g. authorization tokens, secrets, user-specific data, etc. - - **`run_id`**: Globally unique identifier for the overall run. - - **`execution_id`**: Unique identifier for the specific tool execution. - - **`created_at`**: Timestamp indicating when the request was created. +If the `requirements` field is present on a given tool definition, the client MUST provide the required information in the `context` field when calling the tool. -- **Tool Metadata:** +**`context.authorization`** (optional): Contains tokens for authentication. - - **`tool`**: Contains the tool's name, the toolkit to which it belongs, and the toolkit version. +If the `requirements.authorization` field is present on a given tool definition, the client MUST provide the required authorization information in the `context.authorization` field when calling the tool. The client SHOULD obtain authorization tokens itself or through a trusted intermediary. -- **Input Parameters:** +Each item in the `authorization` array is an object with the following properties: - - **`inputs`**: An object containing the parameters needed by the tool. This field supports additional properties to accommodate various tool-specific inputs. +- **`id`**: The unique identifier for the authorization method or authorization provider. +- **`token`**: The token for the tool call. -- **Context:** - - **`context`**: Provides additional execution context including: - - **`authorization`**: Contains tokens for authentication. - - **`secrets`**: Secret information required for execution. - - **`user_id`**: Unique user identifier. - - **`user_info`**: Supplementary information provided by the authorization server. +**`context.secrets`** (optional): Contains secrets for the tool call. -This schema guarantees that every tool call is uniquely identifiable and that the necessary parameters and context for execution are clearly provided. +If the `requirements.secrets` field is present on a given tool definition, the client MUST provide the required secrets in the `context.secrets` field when calling the tool. The client SHOULD obtain secrets itself or through a trusted intermediary. ---- +Each item in the `secrets` array is an object with the following properties: + +- **`id`**: The unique identifier for the secret. + +#### Tool Version Resolution + +Tools MUST be versioned using semantic versioning. A Tool Server MAY support multiple versions of a given tool, to allow clients to opt-in to new versions while preserving backwards compatibility. + +When a client calls a tool, the server MUST resolve the version of the tool to call. The server MUST use the following rules to resolve the version of the tool to call: + +1. Semantic Versioning: If the `version` field is present on the tool definition and is of the form `x.y.z` where `x`, `y`, and `z` are integers, the server MUST use the exact version specified in the `version` field. For example, `@1.0.0`. +2. Shorthand Versioning: If the `version` field is present on the tool definition and is of the form `x` where `x` is an integer, the server MUST use the version `x.0.0`. For example, `@1` which resolves to `1.0.0`. +3. Implied Latest Version: If the `version` field is not present on the tool definition, the server MUST use the latest version of the tool. + +#### Non-Normative Examples + +1. **Calculator.Add** + + A tool call request to add two numbers. + + ```json + { + "tool_id": "Calculator.Add@1.0.0", + "call_id": "123e4567-e89b-12d3-a456-426614174000", + "input": { + "a": 10, + "b": 5 + } + } + ``` + +2. **Doorbell.Ring (No Output)** + + A tool call request to ring a doorbell. + + ```json + { + "tool_id": "Doorbell.Ring@0.1.0", + "call_id": "223e4567-e89b-12d3-a456-426614174001", + "input": { + "doorbell_id": "doorbell42" + } + } + ``` + +3. **System.GetTimestamp (No Input)** + + A tool call request to retrieve the current system timestamp. + + ```json + { + "tool_id": "System.GetTimestamp@1.0.0", + "call_id": "323e4567-e89b-12d3-a456-426614174002" + } + ``` + +4. **Gmail.GetEmails (OAuth 2.0 Authorization)** + + A tool call request to retrieve emails from Gmail using OAuth 2.0 for authorization. + + ```json + { + "tool_id": "Gmail.GetEmails@1.2.0", + "call_id": "423e4567-e89b-12d3-a456-426614174003", + "trace_id": "trace_123", + "input": { + "query": "is:unread" + }, + "context": { + "authorization": [ + { + "id": "google", + "token": "ya29.a0AfH6SMC..." + } + ], + "user_id": "user_123" + } + } + ``` + +5. **SMS.Send (Secret Requirement)** + + A tool call request to send an SMS using Twilio, which requires a secret. + + ```json + { + "tool_id": "SMS.Send@0.1.2", + "call_id": "523e4567-e89b-12d3-a456-426614174004", + "input": { + "to": "+1234567890", + "message": "Hello from our service!" + }, + "context": { + "secrets": [ + { + "id": "TWILIO_API_KEY", + "value": "TWILIO_SECRET_VALUE" + } + ] + } + } + ``` ### 4.3 Tool Response Schema -The Tool Response Schema defines the structure of the data returned after a tool execution: - -- **Execution Metadata:** - - - **`execution_id`**: The globally unique execution identifier. - - **`duration`**: Execution time in milliseconds. - - **`finished_at`**: Timestamp marking the completion of the execution. - - **`success`**: Boolean flag indicating the success or failure of the execution. - -- **Output Content:** - The output can take one of several forms: - 1. **Value Response:** - - Contains a `value` field that may be a JSON object, number, string, or boolean. - 2. **Error Response:** - - Contains an `error` object with: - - **`message`**: A user-facing error message. - - **`developer_message`**: Detailed error information for internal debugging. - - **`can_retry`**: Indicates if the request is retryable. - - **`additional_prompt_content`**: Extra content to be used for retry prompts. - - **`retry_after_ms`**: Suggested delay before retrying. - 3. **Authorization Response:** - - Contains a `requires_authorization` object detailing: - - **`id`**: Identifier for tracking authorization status. - - **`url`**: Redirect URL for obtaining authorization. - - **`scopes`**: Array of authorization scopes required. - - **`status`**: Current authorization status. - 4. **Artifact Response:** - - Contains an `artifact` object describing: - - **`url`**: Location of the stored artifact. - - **`content_type`**: MIME type of the artifact. - - **`size`**: Size of the artifact in bytes. - - **`meta`**: Metadata including a human-readable description. - -The Tool Response Schema ensures that every response provides clear and actionable information regarding the outcome of the tool call. +The `CallToolResponse` schema defines the structure of the data returned from a tool call. + +#### Execution Metadata + +- **`call_id`**: A unique identifier for this call. +- **`success`**: Boolean flag indicating the success or failure of the call. +- **`duration`** (optional): Call time in milliseconds. + +#### Output Content + +The output can take one of several forms: + +1. **Value Response:** + - Contains a `value` field that MUST be a JSON object, number, string, or boolean. +2. **Null Response:** + - Does not contain a `value` field. +3. **Error Response:** + - Contains an `error` object with: + - **`message`**: A user-facing error message. + - **`developer_message`** (optional): Detailed error information for internal debugging. + - **`can_retry`** (optional): Indicates if the request can be retried by the client. If unspecified, the client MUST assume the request cannot be retried (`false`). + - **`additional_prompt_content`** (optional): Extra content to be used for retry prompts. + - **`retry_after_ms`** (optional): Suggested delay before retrying. + +The `CallToolResponse` schema ensures that every response provides clear and actionable information regarding the outcome of the tool call. + +#### Retrying Errors + +If `can_retry` is `true`, the client SHOULD retry the tool call after the `retry_after_ms` delay. + +If `additional_prompt_content` is present, the client MAY use it to provide additional context to the AI model when prompting it to retry the tool call. For example, the tool may return a list of suggested values that are close to the expected input for the model to evaluate. + +#### Non-Normative Examples + +1. **Calculator.Add (Success)** + + A response for a tool call to add two numbers. + + ```json + { + "call_id": "123e4567-e89b-12d3-a456-426614174000", + "duration": 50, + "success": true, + "value": 15 + } + ``` + +2. **Doorbell.Ring (Success, No Output)** + + A response for a tool call to ring a doorbell that does not return any output. + + ```json + { + "call_id": "223e4567-e89b-12d3-a456-426614174001", + "duration": 30, + "success": true, + "value": null + } + ``` + +3. **System.GetTimestamp (Success)** + + A response for a tool call that retrieves the current system timestamp. + + ```json + { + "call_id": "323e4567-e89b-12d3-a456-426614174002", + "duration": 25, + "success": true, + "value": { + "timestamp": "2023-10-05T12:00:00Z" + } + } + ``` + +4. **Gmail.GetEmails (Success)** + + A successful response for a Gmail tool call that returns a list of emails. + + ```json + { + "call_id": "423e4567-e89b-12d3-a456-426614174003", + "duration": 120, + "success": true, + "value": { + "emails": [ + { + "id": "email_1", + "subject": "Welcome to Gmail", + "snippet": "Hello, welcome to your inbox!" + }, + { + "id": "email_2", + "subject": "Your Receipt", + "snippet": "Thank you for your purchase..." + } + ] + } + } + ``` + +5. **SMS.Send (Success)** + + A successful response for a tool call that sends an SMS. + + ```json + { + "call_id": "523e4567-e89b-12d3-a456-426614174004", + "duration": 80, + "success": true, + "value": { + "status": "sent" + } + } + ``` + +6. **Error Response with Message and Developer Message** + + A tool call error response that includes both a user-facing message and an internal developer message. + + ```json + { + "call_id": "623e4567-e89b-12d3-a456-426614174005", + "duration": 40, + "success": false, + "error": { + "message": "Could not reach the server", + "developer_message": "The host api.example.com is not reachable" + } + } + ``` + +7. **Error Response with Additional Prompt Content** + + An error response that offers additional context and retry guidance. + + ```json + { + "call_id": "723e4567-e89b-12d3-a456-426614174006", + "duration": 60, + "success": false, + "error": { + "message": "Doorbell ID not found", + "developer_message": "The doorbell with ID 'doorbell1' does not exist.", + "can_retry": true, + "additional_prompt_content": "ids: doorbell42,doorbell84", + "retry_after_ms": 500 + } + } + ``` + +## 5. Communication Flows + +The Open Tool Calling (OTC) standard defines clear communication flows that enable clients to discover available tools and call them. The flows below follow the definitions in the OpenAPI specification (`specification/http/1.0/openapi.json`), ensuring that all tool interactions are consistent, secure, and standardized. + +### Schema Resolution + +The `$schema` field is used in requests and responses to indicate the version of the OTC standard that the client supports. If the `$schema` field is not included, the server MUST assume the client supports the latest version of the OTC standard. + +```json +{ + "$schema": "https://github.com/OpenToolCalling/Specification/tree/main/specification/http/1.0/openapi.json" +} +``` ---- +The schema URI MUST be a valid URI. -## 5. Communication Flow +### 5.1 Server Health Check -1. **Tool Registration:** +An OTC server MUST implement a health check endpoint that returns a 200 OK response if the server is healthy. - - Tools register themselves using the Tool Definition Schema. - - Registries use this information for tool discovery and client-side validation. +#### Flow Details -2. **Invocation:** +- **Request:** + - **Method:** GET + - **Endpoint:** `/health` + - **Security:** No authentication is required. +- **Response:** + - **Status Code:** 200 OK - - An agent creates a tool request following the Tool Request Schema. - - The request includes necessary input parameters, context, and unique identifiers for tracking. +If the server is ready to receive tool calls, the server MUST return a 200 OK response. The server MAY return an HTTP 503 response if it is not ready to receive tool calls. -3. **Execution:** +#### Non-Normative Example: Server Health Check - - The tool processes the request based on its implementation and the provided schema. - - Execution metrics such as duration and timestamps are recorded. +**Request** -4. **Response:** - - Upon completion, the tool returns a response conforming to the Tool Response Schema. - - The response provides either a successful output, an error, authorization instructions, or artifact information. +```http +GET /health HTTP/1.1 +``` ---- +**Response** + +```http +HTTP/1.1 200 OK +``` + +### 5.2 Tool Discovery + +Clients retrieve tool definitions from the Tool Server using the `/tools` endpoint. This flow provides a catalog of tools that the client can use, all of which conform to the `ToolDefinition` schema. + +#### Flow Details + +- **Request:** + - **Method:** GET + - **Endpoint:** `/tools` + - **Security:** Servers MAY require bearer authentication (JWT). Servers that are internet-facing SHOULD require authentication. + - **Payload:** A JSON document containing: + - **`$schema` Field** (optional): The client MAY include a `$schema` field in the request body to indicate the version of the OTC standard that the client supports. If the `$schema` field is not included, the server MUST assume the client supports the latest version of the OTC standard. +- **Response:** + - **Status Code:** 200 OK + - **Content:** A JSON object that includes a `$schema` URI reference (indicating the OTC version) and a `tools` array. Each element in the array is a complete tool definition. If there are no tools available, the `tools` array MUST be empty. + +#### Non-Normative Example: Tool Discovery + +**Request** + +```http +GET /tools HTTP/1.1 +Host: api.example.com +Authorization: Bearer +``` + +**Response (No Tools)** + +```json +{ + "$schema": "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + "tools": [] +} +``` + +**Response (With Tools)** + +```json +{ + "$schema": "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + "tools": [ + { + "id": "Calculator.Add@1.0.0", + "name": "Calculator_Add", + "description": "Adds two numbers together.", + "version": "1.0.0", + "input_schema": { + "parameters": { + "type": "object", + "properties": { + "a": { + "type": "number", + "description": "The first number to add." + }, + "b": { + "type": "number", + "description": "The second number to add." + } + }, + "required": ["a", "b"] + } + }, + "output_schema": { + "type": "number", + "description": "The sum of the two numbers." + } + }, + { + "id": "Doorbell.Ring@0.1.0", + "name": "Doorbell_Ring", + "description": "Rings a doorbell given a doorbell ID.", + "version": "0.1.0", + "input_schema": { + "parameters": { + "type": "object", + "properties": { + "doorbell_id": { + "type": "string", + "description": "The ID of the doorbell to ring." + } + }, + "required": ["doorbell_id"] + } + }, + "output_schema": null + } + ] +} +``` + +### 5.3 Tool Execution + +Tool execution is initiated by sending a POST request to the `/tools/call` endpoint. This flow lets clients run a tool and receive its output, with the request and response bodies conforming to the `CallToolRequest` and `CallToolResponse` schemas. + +#### Flow Details + +- **Request:** + - **Method:** POST + - **Endpoint:** `/tools/call` + - **Security:** Servers MAY require bearer authentication (JWT). Servers that are internet-facing SHOULD require authentication. + - **Payload:** A JSON document containing: + - **`$schema` Field** (optional): The client MAY include a `$schema` field in the request body to indicate the version of the OTC standard that the client supports. If the `$schema` field is not included, the server MUST assume the client supports the latest version of the OTC standard. + - **`request` Object:** A JSON document following the `CallToolRequest` schema. +- **Response (Tool Execution):** + - **Status Code:** 200 OK + - **Content:** A JSON document following the `CallToolResponse` schema. +- **Response (Server Error):** + - **Status Code:** 400 + - **Content:** A JSON document following the `ServerErrorResponse` schema. +- **Response (Input Validation Error):** + - **Status Code:** 422 + - **Content:** A JSON document following the `ValidationErrorResponse` schema. + +Servers MUST differentiate between: + +1. Errors that occur before the tool is called. +2. Input validation errors. +3. Errors that occur during execution of the tool. + +#### Server Errors + +If an error occurs before the tool is called that is not related to input validation, the server MUST return a 400 response conforming to the `ServerErrorResponse` schema. Examples of such errors include: + +- The tool server is temporarily unavailable. +- The requested version of the OTC standard is not supported. +- The requested tool ID is invalid or cannot be found. +- The requested tool version is not available. +- The tool server requires authentication, but the client did not provide valid credentials. + +The `message` field MUST be present and SHOULD be a user-facing error message. The `developer_message` field MAY be present and SHOULD be an internal message that will be logged but will not be shown to the user or the AI model. + +#### Input Validation + +When a valid tool ID and version are provided, servers MUST validate the input parameters against the tool's `input_schema`. If the input parameters are invalid, the server MUST return a 422 response conforming to the `ValidationErrorResponse` schema. Servers MAY return a `parameter_errors` object that maps parameter names to error messages. + +#### Tool Execution Errors + +If an error occurs during execution of a tool, the server MUST return a 200 response conforming to the `CallToolResponse` schema, with a `success: false` and an `error` object. + +#### Non-Normative Example: Tool Call + +**Request** + +```http +POST /call HTTP/1.1 +Host: api.example.com +Content-Type: application/json +Authorization: Bearer + +{ + "$schema": "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + "request": { + "call_id": "123e4567-e89b-12d3-a456-426614174000", + "tool_id": "Calculator.Add@1.0.0", + "input": { + "a": 1, + "b": 2 + } + } +} +``` + +**Response (Successful Execution)** + +```http +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "$schema": "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + "result": { + "call_id": "123e4567-e89b-12d3-a456-426614174000", + "duration": 2, + "success": true, + "value": 3 + } +} +``` + +**Response (Server Error)** + +```http +HTTP/1.1 400 Bad Request +Content-Type: application/json + +{ + "$schema": "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + "message": "Tool call failed", + "developer_message": "Calculator.Add@2.0.0 is not available" +} +``` + +**Response (Input Validation Error)** + +```http +HTTP/1.1 422 Unprocessable Entity +Content-Type: application/json + +{ + "$schema": "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + "message": "Some input parameters are invalid", + "parameter_errors": { + "a": "Must be a number", + "b": "Must be a number" + } +} +``` + +**Response (Tool Execution Error)** + +```http +HTTP/1.1 200 OK +Content-Type: application/json + +{ + "$schema": "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + "result": { + "call_id": "723e4567-e89b-12d3-a456-426614174006", + "duration": 60, + "success": false, + "error": { + "message": "Doorbell ID not found", + "developer_message": "The doorbell with ID 'doorbell1' does not exist.", + "can_retry": true, + "additional_prompt_content": "ids: doorbell42,doorbell84", + "retry_after_ms": 500 + } + } +} +``` ## 6. Security and Authorization -Security is a critical component of the Open Tool Calling Standard. The following measures are incorporated: +Security is a critical component of the Open Tool Calling standard. -- **Authorization:** - Tools may require token-based or other forms of authorization, as specified in the `requirements.authorization` field of the Tool Definition Schema. -- **Secrets Management:** - Sensitive information is handled via the `requirements.secrets` field. -- **Contextual Security:** - The Tool Request Schema includes contextual information such as user identity and authorization tokens, which help ensure secure execution. +### Server Authentication -These security measures are intended to protect the integrity of tool interactions and ensure that only authorized agents can invoke tool functions. +Server authentication describes how the server authenticates the client: which clients are allowed to make OTC protocol requests to the Tool Server. ---- +Servers that are internet-facing SHOULD require authentication. + +#### No Authentication + +If a server is configured to not require authentication, the server MUST ignore the `Authorization` header. + +#### API Key Authentication + +A static API key is a simple shared secret that both the client and server know. This method provides simple authentication with minimal implementation complexity. + +Requirements: + +- The client MUST include the API key in the `X-API-Key` HTTP header with each request. +- Servers that support this authentication method MUST validate the API key against their stored value. +- Clients and servers MUST transmit API keys only over secure connections (HTTPS). +- Servers MUST reject requests with missing or invalid API keys with a 401 Unauthorized HTTP response. +- API keys SHOULD be generated with sufficient entropy (recommended minimum 32 bytes) and SHOULD be treated as sensitive information. + +**Non-Normative Example: API Key** + +```http +GET /tools HTTP/1.1 +Host: api.example.com +X-API-Key: ahf62jd81hdk19akqnd62hdka +``` + +#### JWT Bearer Token Authentication + +JSON Web Tokens (JWT) as described in [RFC 7519](https://www.rfc-editor.org/rfc/rfc7519) provide a more secure authentication mechanism that doesn't require sending the shared secret with each request. + +Requirements: + +- The client MUST include a valid JWT in the `Authorization` HTTP header using the Bearer scheme. +- The client MUST sign the JWT using the shared secret key using the HS256 algorithm. +- The server MUST validate the JWT signature using the shared secret key. +- The JWT MUST include the `exp` claim, which SHOULD be no more than 15 minutes in the future. +- The JWT MAY include the `aud` claim. If the `aud` claim is present, the server MUST validate it against the server's allowed client list. +- Servers MUST reject requests with missing, invalid, or expired JWTs with a 401 Unauthorized HTTP response. +- Servers SHOULD enforce a reasonably short expiration time for JWTs to limit potential damage from token exposure. + +**Non-Normative Example: JWT Bearer Token** + +```http +GET /tools HTTP/1.1 +Host: api.example.com +Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQiOiJvdGNzZXJ2ZXIiLCJleHAiOjE3NDE3MjQyMTl9.FPIFSSUmngbyePKghI54zUJ-dUxCrh4ZnP9TId5zk34 +``` + +#### Selecting an Authentication Method + +Servers MUST document which authentication methods they support. Servers MAY support multiple authentication methods simultaneously. + +Clients SHOULD prefer JWT Bearer token authentication over static API key authentication when both are available, due to its enhanced security properties. + +For highly sensitive operations or production environments, servers SHOULD consider implementing additional security measures beyond these basic authentication methods, such as IP allowlisting, rate limiting, or more sophisticated authentication protocols. + +### Tool Authorization + +Tool authorization describes how the server authorizes the tool call: given a tool's definition, whether the client needs to authorize the user before calling the tool. + +Tools MAY require token-based or other forms of authorization, as specified in the `requirements.authorization` field of the Tool Definition schema. + +When a given tool describes authorization requirements in the `requirements.authorization` field, the client MUST resolve (or delegate to a trusted intermediary) the authorization requirements and provide the necessary credentials (e.g. a token) in the Tool Call Request, before calling the tool. + +If the client does not provide a valid token in the Tool Call Request for a tool that requires authorization, the server MUST return a 400 Bad Request response as described in the Tool Execution (Server Errors) section. + +#### Non-Normative Example: Tool Authorization Flow + +```mermaid +sequenceDiagram + participant U as User + participant C as Client + participant AS as Authorization Server + participant S as Tool Server + participant T as Tool + + U->>C: Input: "Read my recent emails"
user_id: bob@example.com + Note over C: Tool Gmail.GetEmails has an authorization requirement:
id: google
scopes: [https://www.googleapis.com/auth/gmail.readonly] + C-->>AS: OAuth 2.0 request + AS-->>C: Scoped token for user + C->>S: Call tool Gmail.GetEmails with token + S->>T: Run tool (function) + T->>S: Return tool response + S->>C: Return tool response + +``` + +### Tool Secrets Management + +Tool secrets are sensitive information that is required to call a tool, such as API keys, passwords, and other credentials. + +Tools MAY require secrets, as specified in the `requirements.secrets` field of the Tool Definition schema. + +When a tool requires secrets, the client MUST retrieve the secrets (itself or via a trusted intermediary) and provide them in the Tool Call Request, before calling the tool. + +If the client does not provide a secret in the Tool Call Request for a tool that requires a secret, the server MUST return a 400 Bad Request response as described in the Tool Execution (Server Errors) section. + +#### Non-Normative Example: Tool Secrets Management Flow + +```mermaid +sequenceDiagram + participant U as User + participant C as Client + participant SM as Secrets Manager + participant S as Tool Server + participant T as Tool + + U->>C: Input: "Send an SMS to +15556051234567"
user_id: bob@example.com + Note over C: Tool SMS.Send has a secret requirement:
id: TWILIO_API_KEY + C-->>SM: Get secret TWILIO_API_KEY + SM-->>C: TWILIO_API_KEY=abc123... + C->>S: Call tool SMS.Send with TWILIO_API_KEY=abc123... + S->>T: Run tool (function) + T->>S: Return tool response + S->>C: Return tool response +``` ## 7. Extensibility and Versioning - **Extensibility:** - The Open Tool Calling Standard is designed to be extensible. + The Open Tool Calling standard is designed to be extensible. - New parameters or response types can be added as additional properties in the respective schemas. - - The use of JSON Schema allows for backward-compatible extensions. + - The use of JSON-Schema allows for backward-compatible extensions. - **Versioning:** - - Each toolkit and tool definition must include a version identifier. - - The `$schema` field in each schema helps ensure that both agents and tools are interpreting data according to the correct schema version. + - Each server response must include a `$schema` field that references the version of the Open Tool Calling standard that was used to generate the response. Proper versioning guarantees that changes to the standard do not disrupt existing implementations. ---- - ## 8. Conclusion -The Open Tool Calling Standard provides a robust framework for agent-to-tool communications. By standardizing tool definitions, request formats, and response structures, this standard promotes interoperability, consistency, and security in distributed systems. Adoption of this standard will facilitate seamless integration between diverse agents and tools across multiple platforms. - ---- - -## 9. References - -- JSON Schema Validation Specification, [http://json-schema.org](http://json-schema.org) +The Open Tool Calling standard provides a robust framework for client-to-tool communications. By standardizing tool definitions, request formats, and response structures, this standard promotes interoperability, consistency, and security in distributed systems. Adoption of this standard will facilitate seamless integration between diverse clients and tools across multiple platforms. diff --git a/package.json b/package.json new file mode 100644 index 0000000..252f705 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "open-tool-calling", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "validate-component": "node scripts/validate-component.js", + "validate-request": "node scripts/validate-request.js" + }, + "keywords": [], + "author": "", + "license": "MIT", + "dependencies": { + "ajv": "^8.17.1", + "ajv-formats": "^3.0.1" + } +} diff --git a/scripts/validate-component.js b/scripts/validate-component.js new file mode 100644 index 0000000..9dcbbc2 --- /dev/null +++ b/scripts/validate-component.js @@ -0,0 +1,58 @@ +const Ajv = require("ajv"); +const addFormats = require("ajv-formats"); +const fs = require("fs"); + +// Function to validate JSON against a schema from your OpenAPI spec +function validateAgainstSchema(jsonData, schemaName) { + // Load the OpenAPI spec + const openApiSpec = JSON.parse( + fs.readFileSync("./specification/http/1.0/openapi.json", "utf8") + ); + + // Get the schema by name from components.schemas + const schema = openApiSpec.components.schemas[schemaName]; + + if (!schema) { + throw new Error(`Schema "${schemaName}" not found in the OpenAPI spec`); + } + + // Create Ajv instance with the right options for OpenAPI 3.1 + const ajv = new Ajv({ + strict: false, + allErrors: true, + validateFormats: true, + }); + + // Add formats support (uri, email, etc.) + addFormats(ajv); + + // Add all schemas from the spec to allow for references + for (const [name, schemaObj] of Object.entries( + openApiSpec.components.schemas + )) { + ajv.addSchema(schemaObj, `#/components/schemas/${name}`); + } + + // Validate the data against the schema + const validate = ajv.compile(schema); + const valid = validate(jsonData); + + return { + valid, + errors: validate.errors, + }; +} + +// Example usage +const jsonToValidate = { + call_id: "123e4567-e89b-12d3-a456-426614174000", + duration: 2, + success: true, + value: 3, +}; + +const result = validateAgainstSchema(jsonToValidate, "CallToolResponse"); +console.log(result.valid ? "Validation passed!" : "Validation failed!"); +if (!result.valid) { + console.log(JSON.stringify(result.errors, null, 2)); +} diff --git a/scripts/validate-request.js b/scripts/validate-request.js new file mode 100644 index 0000000..0f6c9cd --- /dev/null +++ b/scripts/validate-request.js @@ -0,0 +1,147 @@ +const Ajv = require("ajv"); +const addFormats = require("ajv-formats"); +const fs = require("fs"); + +// Function to validate request/response against an API path in the OpenAPI spec +function validateAgainstPath( + requestData, + responseData, + statusCode, + pathUrl, + method +) { + // Load the OpenAPI spec + const openApiSpec = JSON.parse( + fs.readFileSync("./specification/http/1.0/openapi.json", "utf8") + ); + + // Get the path definition + const pathDef = openApiSpec.paths[pathUrl]; + if (!pathDef) { + throw new Error(`Path "${pathUrl}" not found in the OpenAPI spec`); + } + + // Get the method definition + const methodDef = pathDef[method.toLowerCase()]; + if (!methodDef) { + throw new Error(`Method "${method}" not found for path "${pathUrl}"`); + } + + // Create Ajv instance with the right options for OpenAPI 3.1 + const ajv = new Ajv({ + strict: false, + allErrors: true, + validateFormats: true, + }); + + // Add formats support (uri, email, etc.) + addFormats(ajv); + + // Add all schemas from the spec to allow for references + for (const [name, schemaObj] of Object.entries( + openApiSpec.components.schemas + )) { + ajv.addSchema(schemaObj, `#/components/schemas/${name}`); + } + + const result = { + requestValid: true, + responseValid: true, + requestErrors: null, + responseErrors: null, + }; + + // Validate request if there's a requestBody in the spec + if ( + methodDef.requestBody && + methodDef.requestBody.content && + methodDef.requestBody.content["application/json"] && + methodDef.requestBody.content["application/json"].schema + ) { + const requestSchema = + methodDef.requestBody.content["application/json"].schema; + const validateRequest = ajv.compile(requestSchema); + result.requestValid = validateRequest(requestData); + result.requestErrors = validateRequest.errors; + } + + // Validate response if there's a response definition for the status code + if ( + methodDef.responses && + methodDef.responses[statusCode] && + methodDef.responses[statusCode].content && + methodDef.responses[statusCode].content["application/json"] && + methodDef.responses[statusCode].content["application/json"].schema + ) { + const responseSchema = + methodDef.responses[statusCode].content["application/json"].schema; + //console.log("Validating response against schema:", responseSchema); + const validateResponse = ajv.compile(responseSchema); + result.responseValid = validateResponse(responseData); + result.responseErrors = validateResponse.errors; + } else { + throw new Error( + `Response for status code "${statusCode}" not found in the OpenAPI spec for path "${pathUrl}" and method "${method}"` + ); + } + + return result; +} + +// Example usage +const requestToValidate = { + $schema: + "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + request: { + call_id: "123e4567-e89b-12d3-a456-426614174000", + tool_id: "Calculator.Add@1.0.0", + input: { + a: 1, + b: 2, + }, + }, +}; + +const responseToValidate = { + $schema: + "https://github.com/ArcadeAI/OpenToolCalling/tree/main/specification/http/1.0/openapi.json", + result: { + call_id: "723e4567-e89b-12d3-a456-426614174006", + duration: 60, + success: false, + error: { + message: "Doorbell ID not found", + developer_message: "The doorbell with ID 'doorbell1' does not exist.", + can_retry: true, + additional_prompt_content: "ids: doorbell42,doorbell84", + retry_after_ms: 500, + }, + }, +}; + +const result = validateAgainstPath( + requestToValidate, + responseToValidate, + "200", + "/tools/call", + "POST" +); + +console.log("Request validation:", result.requestValid ? "Passed!" : "Failed!"); +if (!result.requestValid) { + console.log( + "Request validation errors:", + JSON.stringify(result.requestErrors, null, 2) + ); +} + +console.log( + "Response validation:", + result.responseValid ? "Passed!" : "Failed!" +); +if (!result.responseValid) { + console.log( + "Response validation errors:", + JSON.stringify(result.responseErrors, null, 2) + ); +} diff --git a/specification/http/1.0/execute_tool_request.schema.json b/specification/http/1.0/execute_tool_request.schema.json deleted file mode 100644 index 48eb0f7..0000000 --- a/specification/http/1.0/execute_tool_request.schema.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "$schema": { - "type": "string", - "format": "uri" - }, - "run_id": { - "type": "string", - "description": "The globally-unique run ID provided by the Engine." - }, - "execution_id": { - "type": "string", - "description": "The globally-unique ID for this tool execution in the run." - }, - "created_at": { - "type": "string", - "format": "date-time" - }, - "tool": { - "type": "object", - "properties": { - "name": { - "type": "string", - "description": "Name of the tool to call (invoke)" - }, - "toolkit": { - "type": "string", - "description": "Name of the toolkit containing the tool to call" - }, - "version": { - "type": "string", - "description": "Version of the toolkit containing the tool to call" - } - }, - "required": ["name", "toolkit", "version"], - "additionalProperties": false - }, - "inputs": { - "type": "object", - "additionalProperties": true - }, - "context": { - "type": "object", - "properties": { - "authorization": { - "type": "object", - "properties": { - "token": { - "type": "string" - }, - "additionalProperties": false - } - }, - "secrets": { - "type": "object", - "additionalProperties": true - }, - "user_id": { - "type": "string", - "description": "A unique ID that identifies the user (if any)" - }, - "user_info": { - "type": "object", - "description": "The user information provided by the authorization server (if any)" - } - } - } - }, - "required": ["run_id", "execution_id", "created_at", "tool", "inputs", "context"], - "additionalProperties": false -} diff --git a/specification/http/1.0/execute_tool_response.schema.json b/specification/http/1.0/execute_tool_response.schema.json deleted file mode 100644 index a17cf8e..0000000 --- a/specification/http/1.0/execute_tool_response.schema.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "properties": { - "$schema": { - "type": "string", - "format": "uri" - }, - "execution_id": { - "type": "string", - "description": "The globally-unique ID for this tool execution." - }, - "duration": { - "type": "number", - "description": "The duration of the tool call, in milliseconds" - }, - "finished_at": { - "type": "string", - "format": "date-time", - "description": "The timestamp when the tool execution finished." - }, - "success": { - "type": "boolean", - "description": "Whether the tool execution was successful" - }, - "output": { - "type": "object", - "oneOf": [ - { - "properties": { - "value": { - "description": "The value returned from the function", - "oneOf": [ - { "type": "object", "additionalProperties": true }, - { "type": "number" }, - { "type": "string" }, - { "type": "boolean" } - ] - } - }, - "required": ["value"], - "additionalProperties": false - }, - { - "properties": { - "error": { - "type": "object", - "properties": { - "message": { - "type": "string", - "description": "An error message that can be shown to the user or the AI model" - }, - "developer_message": { - "type": "string", - "description": "An internal message that will be logged but will not be shown to the user or the AI model" - }, - "can_retry": { - "type": "boolean", - "description": "Whether the tool call can be retried", - "default": false - }, - "additional_prompt_content": { - "type": "string", - "description": "Additional content to be included in the retry prompt" - }, - "retry_after_ms": { - "type": "integer", - "description": "The number of milliseconds (if any) to wait before retrying the tool call" - } - }, - "required": ["message"], - "additionalProperties": false - } - }, - "required": ["error"], - "additionalProperties": false - }, - { - "properties": { - "requires_authorization": { - "type": "object", - "properties": { - "id": { - "type": "string", - "description": "The ID for checking the status of the authorization" - }, - "url": { - "type": "string", - "format": "uri", - "description": "The URL to redirect the user to for authorization" - }, - "scopes": { - "type": "array", - "items": { - "type": "string" - }, - "description": "The scopes that are required for authorization" - }, - "status": { - "type": "string", - "description": "The status of the authorization" - } - }, - "required": ["id", "status"], - "additionalProperties": false - } - }, - "required": ["requires_authorization"], - "additionalProperties": false - }, - { - "properties": { - "artifact": { - "type": "object", - "properties": { - "url": { - "type": "string", - "format": "uri", - "description": "The location of the stored artifact" - }, - "content_type": { - "type": "string", - "description": "The MIME Media Type of the data inside the artifact (e.g. text/csv or application/json)" - }, - "size": { - "type": "integer", - "description": "The size of the artifact, in bytes" - }, - "meta": { - "type": "object", - "properties": { - "description": { - "type": "string", - "description": "A descriptive, human-readable explanation of the data inside the artifact" - } - }, - "required": ["description"], - "additionalProperties": false - } - }, - "required": ["url", "content_type", "size", "meta"], - "additionalProperties": false - } - }, - "required": ["artifact"], - "additionalProperties": false - } - ] - } - }, - "required": ["invocation_id", "finished_at", "success"], - "additionalProperties": false -} diff --git a/specification/http/1.0/openapi.json b/specification/http/1.0/openapi.json new file mode 100644 index 0000000..0afa2ad --- /dev/null +++ b/specification/http/1.0/openapi.json @@ -0,0 +1,488 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "Open Tool Calling Standard", + "version": "1.0.0", + "description": "A standard for calling tools (functions or services) in a distributed system.", + "license": { + "name": "MIT", + "url": "https://opensource.org/licenses/MIT" + }, + "contact": { + "url": "https://opentoolcalling.org" + } + }, + "paths": { + "/health": { + "get": { + "operationId": "health-check", + "summary": "Check health", + "description": "Checks the health status of the server.", + "security": [{}], + "responses": { + "200": { + "description": "Server is healthy." + }, + "503": { + "description": "Server is unhealthy and cannot accept requests." + } + } + } + }, + "/tools": { + "get": { + "operationId": "list-tools", + "summary": "List tools", + "description": "Returns a list of tool definitions.", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "required": false, + "content": { + "application/json": { + "schema": { + "properties": { + "$schema": { + "type": "string", + "format": "uri" + } + } + } + } + } + }, + "responses": { + "200": { + "description": "A list of available tools.", + "content": { + "application/json": { + "schema": { + "properties": { + "$schema": { + "type": "string", + "format": "uri" + }, + "tools": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ToolDefinition" + } + } + }, + "required": ["tools"] + } + } + } + }, + "401": { + "description": "Unauthorized. The request requires authentication, but the provided credentials are invalid or missing." + } + } + } + }, + "/tools/call": { + "post": { + "operationId": "call-tool", + "summary": "Call tool", + "description": "Calls a tool with the given parameters.", + "security": [ + { + "bearerAuth": [] + }, + {} + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "properties": { + "$schema": { + "type": "string", + "format": "uri" + }, + "request": { + "$ref": "#/components/schemas/CallToolRequest" + } + }, + "required": ["request"] + } + } + } + }, + "responses": { + "200": { + "description": "Response from tool.", + "content": { + "application/json": { + "schema": { + "properties": { + "$schema": { + "type": "string", + "format": "uri" + }, + "result": { + "$ref": "#/components/schemas/CallToolResponse" + } + }, + "required": ["result"] + } + } + } + }, + "400": { + "description": "The request is invalid or could not be processed.", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ServerErrorResponse" + } + } + } + }, + "401": { + "description": "Unauthorized. The request requires authentication, but the provided credentials are invalid or missing." + }, + "422": { + "description": "The tool call is valid, but the parameters are invalid (missing, incorrect type, etc).", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + } + } + } + } + } + }, + "components": { + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + } + }, + "schemas": { + "ToolId": { + "type": "string", + "description": "A tool's unique identifier in the format 'Toolkit.Tool[@version]', where @version is optional.", + "pattern": "^[A-Za-z0-9_]+\\.[A-Za-z0-9_]+(@([0-9]+|[0-9]+\\.[0-9]+\\.[0-9]+))?$", + "example": [ + "Calculator.Add", + "Calculator.Add@1", + "Calculator.Add@1.0.0" + ] + }, + "ToolVersion": { + "type": "string", + "description": "A tool's semantic version in the format 'x.y.z', where x, y, and z are integers.", + "pattern": "^[0-9]+\\.[0-9]+\\.[0-9]+$", + "example": "1.2.3" + }, + "ToolSecret": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The secret's unique identifier." + }, + "value": { + "type": "string", + "description": "The secret's value." + } + }, + "required": ["id", "value"], + "additionalProperties": true + }, + "ToolDefinition": { + "type": "object", + "properties": { + "id": { + "$ref": "#/components/schemas/ToolId" + }, + "name": { + "type": "string", + "description": "The tool's name. Only allows alphanumeric characters, underscores, and dashes.", + "pattern": "^[A-Za-z0-9_-]{1,64}$", + "example": ["Calculator_Add", "Email_GetEmails"] + }, + "description": { + "type": "string", + "description": "A human-readable explanation of the tool's purpose. This field can be used by both humans and AI models." + }, + "version": { + "$ref": "#/components/schemas/ToolVersion" + }, + "input_schema": { + "type": "object", + "properties": { + "parameters": { + "type": "object", + "additionalProperties": true, + "description": "JSON Schema describing the input parameters for the tool. Supports standard JSON Schema validation but excludes $ref and definitions/schemas for simplicity." + } + }, + "required": ["parameters"], + "additionalProperties": true + }, + "output_schema": { + "oneOf": [ + { + "type": "object", + "additionalProperties": true, + "description": "JSON Schema describing the output parameters for the tool. Supports standard JSON Schema validation but excludes $ref and definitions/schemas for simplicity." + }, + { + "type": "null", + "description": "Null indicates the tool does not return any value." + } + ], + "description": "Schema describing the output of the tool. Can be a JSON Schema object or null if the tool doesn't return a value." + }, + "requirements": { + "type": "object", + "properties": { + "authorization": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "A provider's unique identifier, allowing the tool to specify a specific authorization provider." + }, + "oauth2": { + "type": "object", + "description": "OAuth 2.0-specific authorization details.", + "properties": { + "scopes": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "additionalProperties": true + } + } + }, + "required": ["id"], + "additionalProperties": true + }, + "secrets": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The secret's unique identifier." + } + }, + "required": ["id"], + "additionalProperties": true + } + }, + "user_id": { + "type": "boolean", + "description": "Whether the tool requires a user ID." + } + }, + "additionalProperties": true + } + }, + "required": [ + "id", + "name", + "description", + "input_schema", + "output_schema" + ], + "additionalProperties": false + }, + "CallToolRequest": { + "type": "object", + "properties": { + "call_id": { + "type": "string", + "description": "A unique identifier (e.g. UUID) for this tool call. Used as an idempotency key. If omitted, the server will generate an ID." + }, + "trace_id": { + "type": "string", + "description": "An optional trace identifier for the tool call." + }, + "tool_id": { + "$ref": "#/components/schemas/ToolId" + }, + "input": { + "type": "object", + "description": "The input parameters for the tool call.", + "additionalProperties": true + }, + "context": { + "type": "object", + "properties": { + "authorization": { + "type": "array", + "description": "The authorization information for the tool call.", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The unique identifier for the authorization method or authorization provider." + }, + "token": { + "type": "string", + "description": "The token for the tool call." + } + }, + "required": ["id", "token"], + "additionalProperties": true + } + }, + "secrets": { + "type": "array", + "description": "The secrets for the tool call.", + "items": { + "$ref": "#/components/schemas/ToolSecret" + }, + "additionalProperties": true + }, + "user_id": { + "type": "string", + "description": "A unique ID that identifies the user, if required by the tool." + } + }, + "additionalProperties": true + } + }, + "required": ["tool_id"], + "additionalProperties": false + }, + "CallToolResponse": { + "type": "object", + "properties": { + "call_id": { + "type": "string", + "description": "The unique identifier (e.g. UUID) for this tool call. If an ID is not provided by the client, the server will generate one." + }, + "duration": { + "type": "number", + "description": "The runtime duration of the tool call, in milliseconds" + }, + "success": { + "type": "boolean", + "description": "Whether the tool call was successful. If the `error` field is present, this field will be false." + } + }, + "required": ["call_id", "success"], + "oneOf": [ + { + "properties": { + "success": { "enum": [true] }, + "value": { + "type": [ + "object", + "array", + "string", + "number", + "boolean", + "null" + ], + "additionalProperties": true, + "description": "The value returned from the tool." + } + }, + "not": { "required": ["error"] } + }, + { + "properties": { + "success": { "enum": [false] }, + "error": { + "$ref": "#/components/schemas/ToolError" + } + }, + "required": ["error"], + "not": { "required": ["value"] } + } + ], + "additionalProperties": false + }, + "ServerErrorResponse": { + "type": "object", + "properties": { + "$schema": { + "type": "string", + "format": "uri" + }, + "message": { + "type": "string", + "description": "The error message." + }, + "developer_message": { + "type": "string", + "description": "An internal message that will be logged but will not be shown to the user or the AI model" + } + }, + "required": ["message"], + "additionalProperties": true + }, + "ValidationErrorResponse": { + "type": "object", + "properties": { + "$schema": { + "type": "string", + "format": "uri" + }, + "message": { + "type": "string", + "description": "The error message." + }, + "parameter_errors": { + "type": "object", + "description": "A map of parameter names to error messages, if parameter-level errors are present." + } + }, + "required": ["message"], + "additionalProperties": true + }, + "ToolError": { + "type": "object", + "description": "An error that occurred inside the tool function.", + "properties": { + "message": { + "type": "string", + "description": "An error message that can be shown to the user or the AI model." + }, + "developer_message": { + "type": "string", + "description": "An internal message that will be logged but will not be shown to the user or the AI model." + }, + "can_retry": { + "type": "boolean", + "description": "Whether the tool call can be retried by the client.", + "default": false + }, + "additional_prompt_content": { + "type": "string", + "description": "Additional content to be included in the retry prompt." + }, + "retry_after_ms": { + "type": "integer", + "description": "The number of milliseconds (if any) to wait before retrying the tool call." + } + }, + "required": ["message"], + "additionalProperties": true + } + } + } +} diff --git a/specification/http/1.0/tool_definition.schema.json b/specification/http/1.0/tool_definition.schema.json deleted file mode 100644 index 794a563..0000000 --- a/specification/http/1.0/tool_definition.schema.json +++ /dev/null @@ -1,207 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$defs": { - "primitives": { - "description": "All supported primitive data types", - "type": "string", - "enum": ["string", "integer", "number", "boolean", "json"] - }, - "value_schema": { - "type": "object", - "description": "The schema of a value (e.g. function input parameter value)", - "properties": { - "val_type": { - "oneOf": [{ "$ref": "#/$defs/primitives" }, { "type": "string", "enum": ["array"] }] - }, - "inner_val_type": { - "description": "If the value type is a list, the type of the list values.", - "oneOf": [{ "$ref": "#/$defs/primitives" }, { "type": "null" }] - }, - "enum": { - "oneOf": [ - { "type": "null" }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - } - }, - "required": ["val_type"], - "additionalProperties": false, - "if": { - "properties": { "val_type": { "const": "array" } } - }, - "then": { - "required": ["inner_val_type"] - } - } - }, - "type": "object", - "properties": { - "$schema": { - "type": "string", - "format": "uri" - }, - "name": { - "type": "string", - "description": "The tool name" - }, - "fully_qualified_name": { - "type": "string", - "description": "The tool's fully-qualified name" - }, - "description": { - "type": "string", - "description": "A human-readable description of the tool and when to use it" - }, - "toolkit": { - "type": "object", - "description": "The toolkit that contains the tool", - "properties": { - "name": { - "type": "string", - "description": "The name of the toolkit" - }, - "description": { - "type": "string", - "description": "A human-readable description of the toolkit" - }, - "version": { - "type": "string", - "description": "An identifier for this version of the toolkit" - } - }, - "required": ["name", "version"], - "additionalProperties": false - }, - "input": { - "type": "object", - "properties": { - "parameters": { - "type": "array", - "minItems": 0, - "items": { - "type": "object", - "properties": { - "name": { - "description": "The human-readable name of this parameter.", - "type": "string" - }, - "required": { - "description": "Whether this parameter is required (true) or optional (false).", - "type": "boolean" - }, - "description": { - "description": "A descriptive, human-readable explanation of the parameter.", - "type": "string" - }, - "value_schema": { - "$ref": "#/$defs/value_schema" - }, - "inferrable": { - "type": "boolean", - "description": "Whether a value for this parameter can be inferred by a model. Defaults to `true`.", - "default": true - } - }, - "required": ["name", "required", "value_schema"], - "additionalProperties": false - } - } - }, - "required": ["parameters"], - "additionalProperties": false - }, - "output": { - "type": "object", - "properties": { - "available_modes": { - "type": "array", - "minItems": 1, - "items": { - "type": "string", - "enum": ["value", "error", "null", "artifact", "requires_authorization"] - } - }, - "description": { - "description": "A descriptive, human-readable explanation of the function's output.", - "type": "string" - }, - "value_schema": { - "$ref": "#/$defs/value_schema" - } - }, - "required": ["available_modes"], - "additionalProperties": false - }, - "requirements": { - "type": "object", - "properties": { - "secrets": { - "oneOf": [ - { "type": "null" }, - { - "type": "array", - "items": { - "type": "object", - "properties": { - "key_id": { - "type": "string" - } - }, - "required": ["key_id"], - "additionalProperties": false - } - } - ] - }, - "authorization": { - "oneOf": [ - { "type": "null" }, - { - "type": "string", - "enum": ["none", "token"] - }, - { - "type": "object", - "properties": { - "provider_id": { - "type": "string", - "description": "The provider ID configured in Arcade that acts as an alias to well-known configuration." - }, - "provider_type": { - "type": "string", - "description": "The type of the authorization provider." - }, - "id": { - "type": "string", - "description": "A provider's unique identifier, allowing the tool to specify a specific authorization provider. Recommended for private tools only." - }, - "oauth2": { - "type": "object", - "properties": { - "scopes": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "additionalProperties": false - } - }, - "required": ["provider_type"], - "additionalProperties": false - } - ] - } - }, - "additionalProperties": false - } - }, - "required": ["name", "fully_qualified_name", "toolkit", "input", "output"], - "additionalProperties": false -}