Tool Catalog API Reference¶
This document provides comprehensive documentation for all built-in tools in the Adaptive Sentience platform. Each tool includes detailed schemas, examples, and usage guidance.
Overview¶
Tools are the fundamental execution units in Adaptive Sentience. They are:
- Deterministic: Same inputs produce same outputs (for most tools)
- Schema-validated: Inputs automatically validated against JSON Schema
- Capability-gated: Execution requires specific capability tokens
- Versioned: Semantic versioning for backward compatibility
- Tagged: Policy tags enable automatic policy enforcement
Tool Discovery¶
Tools can be discovered through multiple interfaces:
Via HTTP Gateway¶
Via MCP Server¶
curl -X POST http://127.0.0.1:8787/mcp \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}'
Via Python¶
from clients.unified_client import UnifiedToolClient
client = UnifiedToolClient()
toolhost = client.get_local_toolhost()
tools = toolhost.list_tools()
for tool in tools:
print(f"{tool['name']} v{tool['version']}: {tool['description']}")
Tool Schema Format¶
Each tool has a standardized schema:
@dataclass
class ToolSchema:
tool_id: str # Stable identifier (e.g., "tool:pii_redact")
name: str # Short name used by gateway/toolhost
version: str # Semantic version
description: str # Human-readable description
input_schema: Dict # JSON Schema for input validation
output_schema: Dict # JSON Schema for output structure
required_capabilities: list[str] # Capability tokens required
policy_tags: list[str] # Tags for policy enforcement
deterministic: bool # Whether tool is deterministic
Built-in Tools¶
1. unit_convert¶
Convert between units of measurement (length, temperature, mass).
Tool ID: tool:unit_convert
Version: 1.0.0
Deterministic: Yes
Required Capabilities:
- tool:unit_convert
Policy Tags:
- pure - No side effects
- deterministic - Same inputs → same outputs
- no_network - No network access required
Input Schema¶
{
"type": "object",
"properties": {
"value": {
"type": "number",
"description": "Numeric value to convert"
},
"from_unit": {
"type": "string",
"description": "Source unit (e.g., 'km', 'mi', 'c', 'f', 'kg', 'lb')"
},
"to_unit": {
"type": "string",
"description": "Target unit (e.g., 'km', 'mi', 'c', 'f', 'kg', 'lb')"
}
},
"required": ["value", "from_unit", "to_unit"],
"additionalProperties": false
}
Supported Units¶
Length:
- m, meter, meters → Meters
- ft, foot, feet → Feet
- km, kilometer, kilometers → Kilometers
- mi, mile, miles → Miles
Temperature:
- c, celsius → Celsius
- f, fahrenheit → Fahrenheit
Mass:
- kg, kilogram, kilograms → Kilograms
- lb, lbs, pound, pounds → Pounds
Output Schema¶
{
"type": "object",
"properties": {
"value": {
"type": "number",
"description": "Converted value"
},
"from_unit": {
"type": "string",
"description": "Original unit"
},
"to_unit": {
"type": "string",
"description": "Target unit"
}
},
"required": ["value", "from_unit", "to_unit"]
}
Examples¶
Example 1: Miles to Kilometers
curl -X POST http://127.0.0.1:8787/v1/tool_call \
-H "Content-Type: application/json" \
-d '{
"target": {"kind": "local"},
"tool_name": "unit_convert",
"tool_args": {
"value": 10,
"from_unit": "miles",
"to_unit": "km"
}
}'
Response:
Example 2: Celsius to Fahrenheit
from clients.unified_client import UnifiedToolClient
client = UnifiedToolClient()
result = client.call_tool_local("unit_convert", {
"value": 100,
"from_unit": "celsius",
"to_unit": "fahrenheit"
})
print(f"100°C = {result['value']}°F") # 100°C = 212.0°F
Example 3: Pounds to Kilograms
result = client.call_tool_local("unit_convert", {
"value": 150,
"from_unit": "pounds",
"to_unit": "kg"
})
print(f"150 lbs = {result['value']} kg") # 150 lbs = 68.0388 kg
Example 4: Feet to Meters
result = client.call_tool_local("unit_convert", {
"value": 100,
"from_unit": "feet",
"to_unit": "meters"
})
print(f"100 ft = {result['value']} m") # 100 ft = 30.48 m
Error Handling¶
try:
result = client.call_tool_local("unit_convert", {
"value": 10,
"from_unit": "invalid_unit",
"to_unit": "km"
})
except ValueError as e:
print(f"Error: {e}") # Error: Unsupported unit: invalid_unit
2. pii_redact¶
Redact personally identifiable information (PII) from text using regex patterns.
WARNING: This is a heuristic demo implementation, NOT production-grade PII detection. For production use, employ specialized PII detection services with ML-based entity recognition.
Tool ID: tool:pii_redact
Version: 1.0.0
Deterministic: Yes
Required Capabilities:
- tool:pii_redact
Policy Tags:
- pii - Handles PII data
- privacy - Privacy-sensitive operation
- pure - No side effects
- no_network - No network access required
Input Schema¶
{
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Text to redact PII from"
},
"redact_emails": {
"type": "boolean",
"description": "Whether to redact email addresses",
"default": true
},
"redact_phones": {
"type": "boolean",
"description": "Whether to redact phone numbers",
"default": true
},
"replacement": {
"type": "string",
"description": "Replacement text for redacted content",
"default": "[REDACTED]"
}
},
"required": ["text"],
"additionalProperties": false
}
Detection Patterns¶
Email Pattern:
- Regex: \b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b
- Matches: user@example.com, admin.user@company.co.uk
Phone Patterns (US-centric):
- 123-456-7890
- 123.456.7890
- 123 456 7890
- (123) 456-7890
- (123)456-7890
- 1234567890
Output Schema¶
{
"type": "object",
"properties": {
"redacted_text": {
"type": "string",
"description": "Text with PII redacted"
},
"redactions": {
"type": "array",
"description": "List of redactions performed",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["email", "phone"]
},
"count": {
"type": "integer"
}
},
"required": ["type", "count"]
}
}
},
"required": ["redacted_text", "redactions"]
}
Examples¶
Example 1: Redact Email
curl -X POST http://127.0.0.1:8787/v1/tool_call \
-H "Content-Type: application/json" \
-d '{
"target": {"kind": "local"},
"tool_name": "pii_redact",
"tool_args": {
"text": "Contact support at admin@company.com for assistance"
}
}'
Response:
{
"ok": true,
"result": {
"redacted_text": "Contact support at [REDACTED] for assistance",
"redactions": [
{
"type": "email",
"count": 1
}
]
}
}
Example 2: Redact Phone Number
result = client.call_tool_local("pii_redact", {
"text": "Call me at 555-123-4567 or (555) 987-6543"
})
print(result["redacted_text"])
# Output: "Call me at [REDACTED] or [REDACTED]"
print(result["redactions"])
# Output: [{"type": "phone", "count": 2}]
Example 3: Custom Replacement
result = client.call_tool_local("pii_redact", {
"text": "Email: john@example.com, Phone: 555-1234",
"replacement": "***HIDDEN***"
})
print(result["redacted_text"])
# Output: "Email: ***HIDDEN***, Phone: ***HIDDEN***"
Example 4: Selective Redaction
# Only redact emails, keep phone numbers
result = client.call_tool_local("pii_redact", {
"text": "Contact: admin@example.com or 555-123-4567",
"redact_emails": True,
"redact_phones": False
})
print(result["redacted_text"])
# Output: "Contact: [REDACTED] or 555-123-4567"
Example 5: Multiple PII Types
result = client.call_tool_local("pii_redact", {
"text": """
Customer report:
Name: John Doe
Email: john.doe@customer.com
Phone: (555) 123-4567
Alt Email: j.doe@gmail.com
Mobile: 555.987.6543
"""
})
print(result["redacted_text"])
# Emails and phones are redacted
print(result["redactions"])
# [{"type": "email", "count": 2}, {"type": "phone", "count": 2}]
3. jsonschema_validate¶
Validate data against a JSON Schema with detailed error messages.
Tool ID: tool:jsonschema_validate
Version: 1.0.0
Deterministic: Yes
Required Capabilities:
- tool:jsonschema_validate
Policy Tags:
- validation - Data validation operation
- pure - No side effects
- deterministic - Same inputs → same outputs
- no_network - No network access required
Input Schema¶
{
"type": "object",
"properties": {
"schema": {
"type": "object",
"description": "JSON Schema to validate against"
},
"data": {
"description": "Data to validate (any type)"
}
},
"required": ["schema", "data"],
"additionalProperties": false
}
Output Schema¶
{
"type": "object",
"properties": {
"valid": {
"type": "boolean",
"description": "Whether data is valid"
},
"errors": {
"type": "array",
"description": "Validation error messages",
"items": {
"type": "string"
}
}
},
"required": ["valid", "errors"]
}
Examples¶
Example 1: Valid User Schema
result = client.call_tool_local("jsonschema_validate", {
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"age": {"type": "number", "minimum": 0},
"email": {"type": "string", "format": "email"}
},
"required": ["name", "age"]
},
"data": {
"name": "Alice",
"age": 30,
"email": "alice@example.com"
}
})
print(f"Valid: {result['valid']}") # True
print(f"Errors: {result['errors']}") # []
Example 2: Invalid Data (Missing Required Field)
result = client.call_tool_local("jsonschema_validate", {
"schema": {
"type": "object",
"properties": {
"name": {"type": "string"},
"email": {"type": "string"}
},
"required": ["name", "email"]
},
"data": {
"name": "Bob"
# Missing email
}
})
print(f"Valid: {result['valid']}") # False
print(f"Errors: {result['errors']}")
# ["'email' is a required property"]
Example 3: Type Validation
result = client.call_tool_local("jsonschema_validate", {
"schema": {
"type": "object",
"properties": {
"count": {"type": "integer"},
"price": {"type": "number"}
}
},
"data": {
"count": "not_a_number",
"price": 29.99
}
})
print(f"Valid: {result['valid']}") # False
print(f"Errors: {result['errors']}")
# ["'not_a_number' is not of type 'integer'"]
Example 4: Array Validation
result = client.call_tool_local("jsonschema_validate", {
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"id": {"type": "integer"},
"name": {"type": "string"}
},
"required": ["id", "name"]
},
"minItems": 1
},
"data": [
{"id": 1, "name": "Item 1"},
{"id": 2, "name": "Item 2"}
]
})
print(f"Valid: {result['valid']}") # True
Example 5: Enum Validation
result = client.call_tool_local("jsonschema_validate", {
"schema": {
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["pending", "active", "completed"]
}
},
"required": ["status"]
},
"data": {
"status": "invalid_status"
}
})
print(f"Valid: {result['valid']}") # False
print(f"Errors: {result['errors']}")
# ["'invalid_status' is not one of ['pending', 'active', 'completed']"]
Example 6: Complex Nested Schema
curl -X POST http://127.0.0.1:8787/v1/tool_call \
-H "Content-Type: application/json" \
-d '{
"target": {"kind": "local"},
"tool_name": "jsonschema_validate",
"tool_args": {
"schema": {
"type": "object",
"properties": {
"user": {
"type": "object",
"properties": {
"name": {"type": "string"},
"contacts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {"type": "string", "enum": ["email", "phone"]},
"value": {"type": "string"}
},
"required": ["type", "value"]
}
}
},
"required": ["name"]
}
},
"required": ["user"]
},
"data": {
"user": {
"name": "Alice",
"contacts": [
{"type": "email", "value": "alice@example.com"},
{"type": "phone", "value": "555-1234"}
]
}
}
}
}'
4. doc_summarize¶
Create extractive summary of text using frequency-based sentence scoring.
Note: This is a simple heuristic approach. For production use, employ specialized NLP/LLM-based summarization services.
Tool ID: tool:doc_summarize
Version: 1.0.0
Deterministic: Yes
Required Capabilities:
- tool:doc_summarize
Policy Tags:
- nlp - Natural language processing
- pure - No side effects
- no_network - No network access required
Input Schema¶
{
"type": "object",
"properties": {
"text": {
"type": "string",
"description": "Text to summarize"
},
"max_sentences": {
"type": "integer",
"description": "Maximum number of sentences in summary",
"default": 3,
"minimum": 1
}
},
"required": ["text"],
"additionalProperties": false
}
Output Schema¶
{
"type": "object",
"properties": {
"summary": {
"type": "string",
"description": "Extractive summary"
},
"original_sentences": {
"type": "integer",
"description": "Number of sentences in original text"
},
"summary_sentences": {
"type": "integer",
"description": "Number of sentences in summary"
},
"method": {
"type": "string",
"description": "Summarization method used"
}
},
"required": ["summary", "original_sentences", "summary_sentences", "method"]
}
Summarization Algorithm¶
- Sentence Splitting: Split text into sentences using
.!?delimiters - Word Tokenization: Extract words using regex
\b\w+\b - Stop Word Removal: Filter common words (the, a, an, and, etc.)
- Frequency Counting: Count word frequencies in the document
- Sentence Scoring: Score sentences by sum of word frequencies
- Top-K Selection: Select top K sentences by score
- Re-ordering: Restore original sentence order
Examples¶
Example 1: Summarize Article
text = """
Artificial intelligence is transforming how businesses operate.
Machine learning algorithms can analyze vast amounts of data quickly.
Companies are using AI to improve customer service and operations.
However, ethical considerations around AI deployment remain important.
Privacy concerns and algorithmic bias need to be addressed.
The future of AI depends on responsible development practices.
Regulations are being developed to ensure AI safety.
"""
result = client.call_tool_local("doc_summarize", {
"text": text,
"max_sentences": 3
})
print(result["summary"])
# Output: Top 3 most important sentences based on word frequency
print(f"Original: {result['original_sentences']} sentences")
print(f"Summary: {result['summary_sentences']} sentences")
Example 2: Short Summary
curl -X POST http://127.0.0.1:8787/v1/tool_call \
-H "Content-Type: application/json" \
-d '{
"target": {"kind": "local"},
"tool_name": "doc_summarize",
"tool_args": {
"text": "The quick brown fox jumps over the lazy dog. This is a test sentence. Another sentence for testing.",
"max_sentences": 2
}
}'
Response:
{
"ok": true,
"result": {
"summary": "The quick brown fox jumps over the lazy dog. This is a test sentence.",
"original_sentences": 3,
"summary_sentences": 2,
"method": "extractive-frequency"
}
}
Example 3: Single Sentence Summary
result = client.call_tool_local("doc_summarize", {
"text": """
Climate change is one of the biggest challenges facing humanity.
Rising temperatures are causing extreme weather events.
Scientists agree that immediate action is needed.
Renewable energy adoption is increasing globally.
However, more investment is required to meet climate goals.
""",
"max_sentences": 1
})
print(result["summary"])
# Returns the single most important sentence
Example 4: Already Short Text
result = client.call_tool_local("doc_summarize", {
"text": "This is a short text.",
"max_sentences": 5
})
print(result["summary"])
# Output: "This is a short text."
print(result["original_sentences"]) # 1
print(result["summary_sentences"]) # 1
Tool Versioning¶
Tools use semantic versioning (MAJOR.MINOR.PATCH):
- MAJOR: Breaking changes to input/output schemas
- MINOR: New features (backward compatible)
- PATCH: Bug fixes (backward compatible)
Example version history:
tool:pii_redact
1.0.0 - Initial release
1.1.0 - Added SSN redaction (new feature)
1.1.1 - Fixed phone number regex (bug fix)
2.0.0 - Changed output format (breaking change)
Querying Available Tools¶
Via HTTP Gateway¶
# Get local catalog
curl http://127.0.0.1:8787/v1/catalog
# Get mesh catalog with enrichment
curl "http://127.0.0.1:8787/v1/catalog?enrich=true"
Via MCP¶
import requests
response = requests.post(
"http://127.0.0.1:8787/mcp",
json={
"jsonrpc": "2.0",
"id": 1,
"method": "tools/list",
"params": {}
}
)
tools = response.json()["result"]["tools"]
for tool in tools:
print(f"{tool['name']}: {tool['description']}")
Via Python Client¶
from clients.unified_client import UnifiedToolClient
client = UnifiedToolClient()
toolhost = client.get_local_toolhost()
tools = toolhost.list_tools()
# Filter by capability
pii_tools = [t for t in tools if "pii" in t.get("policy_tags", [])]
# Filter by determinism
deterministic_tools = [t for t in tools if t.get("deterministic", False)]
# Get specific tool
for tool in tools:
if tool["name"] == "unit_convert":
print(f"Version: {tool['version']}")
print(f"Capability: {tool['required_capability']}")
Tool Execution Patterns¶
Pattern 1: Local Execution¶
Execute tool on gateway's local toolhost:
from clients.unified_client import UnifiedToolClient
client = UnifiedToolClient()
result = client.call_tool_local("pii_redact", {
"text": "Contact admin@example.com"
})
Pattern 2: Remote Execution¶
Execute tool on specific remote node:
result = client.call_tool_remote(
http_url="http://192.168.1.100:8000",
tool_name="unit_convert",
tool_args={
"value": 10,
"from_unit": "miles",
"to_unit": "km"
}
)
Pattern 3: Auto-Routing¶
Let gateway choose best available node:
curl -X POST http://127.0.0.1:8787/v1/tool_call \
-H "Content-Type: application/json" \
-d '{
"target": {"kind": "auto"},
"tool_name": "doc_summarize",
"tool_args": {
"text": "Long document here...",
"max_sentences": 3
}
}'
Pattern 4: Workflow Chaining¶
Chain multiple tools together:
# Step 1: Redact PII
redacted = client.call_tool_local("pii_redact", {
"text": "Contact john@example.com for info about the 10 mile race"
})
# Step 2: Summarize redacted text
summary = client.call_tool_local("doc_summarize", {
"text": redacted["redacted_text"],
"max_sentences": 1
})
# Step 3: Convert units mentioned
conversion = client.call_tool_local("unit_convert", {
"value": 10,
"from_unit": "miles",
"to_unit": "km"
})
print(f"Summary: {summary['summary']}")
print(f"10 miles = {conversion['value']} km")
Policy Enforcement¶
Tools can be filtered by policy tags:
Privacy-Safe Tools¶
privacy_safe = [
t for t in tools
if "privacy" in t.get("policy_tags", [])
or "pii" in t.get("policy_tags", [])
]
Deterministic Tools Only¶
Network-Free Tools¶
Custom Tool Development¶
To create a custom tool, follow this template:
# edge_node/tools/my_tool.py
from typing import Dict, Any
def my_tool(args: Dict[str, Any]) -> Dict[str, Any]:
"""
Tool description.
Args:
args: {
"param1": type,
"param2": type
}
Returns:
{
"result_field": type
}
"""
# Validate inputs
param1 = args.get("param1")
if param1 is None:
raise ValueError("Missing required field: param1")
# Execute logic
result = process(param1)
# Return structured output
return {
"result_field": result
}
Register in catalog:
# catalog/tool_schemas.py
TOOL_SCHEMAS["my_tool"] = ToolSchema(
tool_id="tool:my_tool",
name="my_tool",
version="1.0.0",
description="My custom tool",
input_schema={
"type": "object",
"properties": {
"param1": {"type": "string"}
},
"required": ["param1"]
},
output_schema={
"type": "object",
"properties": {
"result_field": {"type": "string"}
}
},
required_capabilities=["tool:my_tool"],
policy_tags=["custom"],
deterministic=True
)
Testing Tools¶
Unit Testing¶
import pytest
from edge_node.tools.pii_redact import pii_redact
def test_email_redaction():
result = pii_redact({
"text": "Contact admin@example.com"
})
assert "[REDACTED]" in result["redacted_text"]
assert result["redactions"][0]["type"] == "email"
assert result["redactions"][0]["count"] == 1
def test_phone_redaction():
result = pii_redact({
"text": "Call 555-123-4567"
})
assert "[REDACTED]" in result["redacted_text"]
assert result["redactions"][0]["type"] == "phone"
Integration Testing¶
from clients.unified_client import UnifiedToolClient
def test_tool_execution():
client = UnifiedToolClient()
result = client.call_tool_local("unit_convert", {
"value": 10,
"from_unit": "miles",
"to_unit": "km"
})
assert result["value"] == pytest.approx(16.0934, rel=1e-3)
assert result["from_unit"] == "miles"
assert result["to_unit"] == "km"
Performance Considerations¶
Tool Execution Latency¶
Typical latencies (local execution):
| Tool | Avg Latency | Notes |
|---|---|---|
unit_convert |
1-5ms | Pure computation |
pii_redact |
5-15ms | Regex matching |
jsonschema_validate |
10-30ms | Schema traversal |
doc_summarize |
20-100ms | Depends on text length |
Optimization Tips¶
- Cache tool schemas: Avoid repeated schema lookups
- Batch operations: Group multiple tool calls when possible
- Use local execution: Remote calls add network latency (50-200ms)
- Pre-validate inputs: Client-side validation reduces errors
Troubleshooting¶
Common Issues¶
Problem: "Unknown tool" error
Solution: Check tool name spelling and availability
Problem: "Invalid input" error
Solution: Validate against tool schema
from catalog.tool_schemas import get_tool_schema
schema = get_tool_schema("unit_convert")
print(schema.input_schema)
Problem: Tool execution timeout
Solution: Increase timeout or check node connectivity
Changelog¶
- v1.0.0 (2026-01-24): Initial tool catalog
unit_convert: Length, temperature, mass conversionspii_redact: Email and phone number redactionjsonschema_validate: JSON Schema validationdoc_summarize: Extractive text summarization