Skip to main content

Agent Tool Protocol SDK

Project description

Agent Tool Protocol(ATP)

ATP Logo

A Python SDK for registering, exposing, and serving your own Python functions as tools via the ATP platform. Supports secure OAuth2 flows, dynamic tool registration, and real-time tool invocation via WebSocket.


Table of Contents

  • Installation
  • Quick Start
  • Class: ToolKitClient
    • Constructor
    • register_tool
    • start
    • stop
  • Tool Function Requirements
  • WebSocket Events
  • Error Handling
  • Examples
  • Advanced Usage
  • License

Installation

pip install AgentToolProtocol

Quick Start

from atp_sdk.clients import ToolKitClient
import requests

client = ToolKitClient(
    api_key="YOUR_ATP_API_KEY",
    app_name="my_app"
)

@client.register_tool(
    function_name="hello_world",
    params=['name'],
    required_params=['name'],
    description="Returns a greeting.",
    auth_provider=None, auth_type=None, auth_with=None
)
def hello_world(**kwargs):
    return {"message": f"Hello, {kwargs.get('name', 'World')}!"}

client.start()

Class: ToolKitClient

Constructor

ToolKitClient(
    api_key: str,
    app_name: str,
    base_url: str = "https://chatatp-backend.onrender.com"
)

Parameters:

  • api_key (str): Your ATP API key.
  • app_name (str): Name of your application.
  • base_url (str, optional): ATP Server backend URL. Defaults to chatatp-backend.onrender.com.

register_tool

Registers a Python function as a tool with the ATP platform.

@client.register_tool(
    function_name: str,
    params: list[str],
    required_params: list[str],
    description: str,
    auth_provider: Optional[str],
    auth_type: Optional[str],
    auth_with: Optional[str]
)
def my_tool(**kwargs):
    ...

Arguments:

  • function_name: Unique name for the tool.
  • params: List of all parameter names.
  • required_params: List of required parameter names.
  • description: Human-readable description.
  • auth_provider: Name of OAuth2 provider (e.g., "hubspot", "google"), or None.
  • auth_type: Auth type (e.g., "OAuth2"), or None.
  • auth_with: Name of the token parameter (e.g., "access_token"), or None.

Returns:
A decorator to wrap your function.

Example:

@client.register_tool(
    function_name="create_company",
    params=['name', 'domain', 'industry'],
    required_params=['name', 'domain', 'industry'],
    description="Creates a company in HubSpot.",
    auth_provider="hubspot", auth_type="OAuth2", auth_with="access_token"
)
def create_company(**kwargs):
    access_token = kwargs.get('auth_token')
    url = "https://api.hubapi.com/crm/v3/objects/companies"
    headers = {"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"}
    data = {"properties": {
        "name": kwargs.get('name'),
        "domain": kwargs.get('domain'),
        "industry": kwargs.get('industry')
    }}
    response = requests.post(url, json=data, headers=headers)
    return response.json()

start

Starts the WebSocket client and begins listening for tool requests.

client.start()
  • Keeps the main thread alive.
  • Handles reconnections automatically.

stop

Stops the WebSocket client and closes the connection.

client.stop()

Tool Function Requirements

  • Must accept all parameters as **kwargs.
  • If your tool requires authentication, expect auth_token in kwargs.
  • Return a serializable object (dict, str, etc).

WebSocket Events

Tool Registration

Upon registration, your tool is announced to the ATP backend and available for invocation.

Tool Invocation

When a tool request is received, your function is called with the provided parameters and (if needed) auth_token.

Example incoming message:

{
  "message_type": "atp_tool_request",
  "payload": {
    "request_id": "uuid",
    "tool_name": "create_company",
    "params": {"name": "Acme", "domain": "acme.com", "industry": "Tech"},
    "auth_token": "ACCESS_TOKEN"
  }
}

Error Handling

  • If your function raises an exception, the error is caught and returned as:
    {"error": "Error message"}
    
  • If required parameters are missing, an error is returned.
  • If auth_token is required but missing, an error is returned.

Examples

Minimal Tool

@client.register_tool(
    function_name="echo",
    params=['text'],
    required_params=['text'],
    description="Echoes the input text.",
    auth_provider=None, auth_type=None, auth_with=None
)
def echo(**kwargs):
    return {"echo": kwargs.get('text')}

Tool with OAuth2

@client.register_tool(
    function_name="get_contacts",
    params=['auth_token'],
    required_params=['auth_token'],
    description="Fetches contacts from HubSpot.",
    auth_provider="hubspot", auth_type="OAuth2", auth_with="access_token"
)
def get_contacts(**kwargs):
    access_token = kwargs.get('auth_token')
    url = "https://api.hubapi.com/crm/v3/objects/contacts"
    headers = {"Authorization": f"Bearer {access_token}"}
    response = requests.get(url, headers=headers)
    return response.json()

Class: LLMClient

The LLMClient lets you connect to the ATP Agent Server, retrieve toolkit context, and execute tools or workflows using JSON payloads—perfect for LLM-based agents.

Constructor

from atp_sdk.clients import LLMClient

llm_client = LLMClient(
    api_key="YOUR_ATP_API_KEY"
)

get_toolkit_context

Retrieves the toolkit context and system instructions for a given toolkit and user prompt.

context = llm_client.get_toolkit_context(
    toolkit_id="your_toolkit_id",
    user_prompt="What do you want to achieve?"
)

call_toolkit

Executes a tool or workflow on the ATP server.

response = llm_client.call_toolkit(
    toolkit_id="your_toolkit_id",
    json_response=json.dumps({
        "function": "hello_world",
        "parameters": {"name": "Alice"},
        "task_title": "Say hello",
        "execution_type": "remote"
    })
)
print(response)

Example: Using LLMClient with OpenAI, Anthropic, and Mistral AI

You can use any LLM to generate the JSON workflow, then execute each step with LLMClient.

1. OpenAI (GPT-4o)

import openai
from atp_sdk.clients import LLMClient

llm_client = LLMClient(api_key="YOUR_ATP_API_KEY")

# Get toolkit context and system prompt
context = llm_client.get_toolkit_context(toolkit_id="your_toolkit_id", user_prompt="Create a company and then list contacts.")

# Use OpenAI to generate the workflow JSON
response = openai.ChatCompletion.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": context},
        {"role": "user", "content": "Create a company and then list contacts."}
    ]
)
workflow_json = response.choices[0].message.content

# Parse and execute each workflow step
import json
workflow = json.loads(workflow_json)
if "workflows" in workflow:
    results = []
    for step in workflow["workflows"]:
        result = llm_client.call_toolkit(
            toolkit_id="your_toolkit_id",
            json_response=json.dumps(step)
        )
        results.append(result)
else:
    result = llm_client.call_toolkit(
        toolkit_id="your_toolkit_id",
        json_response=workflow_json
    )

2. Anthropic (Claude)

import anthropic
from atp_sdk.clients import LLMClient

llm_client = LLMClient(api_key="YOUR_ATP_API_KEY")
context = llm_client.get_toolkit_context(toolkit_id="your_toolkit_id", user_prompt="...")

client = anthropic.Anthropic(api_key="YOUR_ANTHROPIC_API_KEY")
response = client.messages.create(
    model="claude-3-opus-20240229",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": context}
    ]
)
workflow_json = response.content[0].text

# Execute as above

3. Mistral AI

from mistralai.client import MistralClient
from atp_sdk.clients import LLMClient

llm_client = LLMClient(api_key="YOUR_ATP_API_KEY")
context = llm_client.get_toolkit_context(toolkit_id="your_toolkit_id", user_prompt="...")

client = MistralClient(api_key="YOUR_MISTRAL_API_KEY")
response = client.chat(
    model="mistral-large-latest",
    messages=[{"role": "user", "content": context}]
)
workflow_json = response.choices[0].message.content

# Execute as above

Handling Multi-Step Workflows

When the LLM returns a workflow with multiple steps:

import json

workflow = json.loads(workflow_json)
if "workflows" in workflow:
    results = []
    for step in workflow["workflows"]:
        result = llm_client.call_toolkit(
            toolkit_id="your_toolkit_id",
            json_response=json.dumps(step)
        )
        results.append(result)
else:
    result = llm_client.call_toolkit(
        toolkit_id="your_toolkit_id",
        json_response=workflow_json
    )
  • For each step, call llm_client.call_toolkit with the step JSON.
  • Collect and process results as needed.
  • If a step has "depends_on", you can pass outputs from previous steps as needed.

Example: Full Workflow

from atp_sdk.clients import LLMClient
import openai
import json

llm_client = LLMClient(api_key="YOUR_ATP_API_KEY")
context = llm_client.get_toolkit_context(toolkit_id="your_toolkit_id", user_prompt="...")

response = openai.ChatCompletion.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": context},
        {"role": "user", "content": "Do a multi-step task."}
    ]
)
workflow_json = response.choices[0].message.content
workflow = json.loads(workflow_json)

results = []
if "workflows" in workflow:
    for step in workflow["workflows"]:
        result = llm_client.call_toolkit(
            toolkit_id="your_toolkit_id",
            json_response=json.dumps(step)
        )
        results.append(result)
else:
    result = llm_client.call_toolkit(
        toolkit_id="your_toolkit_id",
        json_response=workflow_json
    )
    results.append(result)

print(results)

Tip:
Always ensure the LLM returns valid JSON as described in the toolkit context instructions.


Advanced Usage

Custom Backend

client = ToolKitClient(
    api_key="YOUR_API_KEY",
    app_name="my_app",
    base_url="https://your-backend.example.com"
)

Multiple Tools

@client.register_tool(...)
def tool1(**kwargs): ...

@client.register_tool(...)
def tool2(**kwargs): ...

Keeping the Main Thread Alive

client.start()
try:
    while True:
        import time; time.sleep(1)
except KeyboardInterrupt:
    client.stop()

License

MIT License.
See LICENSE for details.


Feedback & Issues

For bug reports or feature requests, please open an issue on GitHub.


Happy coding! 🚀

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agenttoolprotocol-0.1.2.tar.gz (10.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agenttoolprotocol-0.1.2-py3-none-any.whl (10.9 kB view details)

Uploaded Python 3

File details

Details for the file agenttoolprotocol-0.1.2.tar.gz.

File metadata

  • Download URL: agenttoolprotocol-0.1.2.tar.gz
  • Upload date:
  • Size: 10.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for agenttoolprotocol-0.1.2.tar.gz
Algorithm Hash digest
SHA256 c13b71a9ffc3bb807717d864f389acc75a680c3270223ca6f8c60856825f252e
MD5 38bef37bb231457b37256da5acc6cbd6
BLAKE2b-256 b9d1a93799870294bba091d01f12526083ef4cad77c14957595b6c29a924d5aa

See more details on using hashes here.

File details

Details for the file agenttoolprotocol-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for agenttoolprotocol-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 0fe31c2ef068f9c0bf5973443689b8d01fe842aa0e0e1ad36660ff35f0fb00b8
MD5 053d69fb07be1391cc58f5a24a2221dc
BLAKE2b-256 bb702ba1082ebf38265d2adf1c6bb2a0ad33b052cd7d879be859d3accc85866e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page