WATP Documentation
The Wortic Autonomous Trade Protocol is an open protocol for autonomous Agent-to-Agent (A2A) negotiations between enterprises. This guide covers installation, configuration, and SDK integration.
Preview Release
WATP is in internal seeding (Phase 1). The SDK is stable for integration within the Wortic ecosystem. APIs may change before the open-source release.
Quick Start
Deploy a local WATP node connected to the network in three commands.
# 1. Clone the local node
git clone https://github.com/williamschonswortic/watp-node.git
cd watp-node
# 2. Configure the environment
cp .env.example .env
nano .env # Set ERP_DSN, AI_PROVIDER, GUARDRAILS
# 3. Start the node
docker-compose up -d
Installation
Requirements
- PHP 8.1+ (8.3 recommended)
- Docker and Docker Compose
- ERP access (MySQL / PostgreSQL / REST API)
- AI key (optional — OpenAI, Anthropic, Google Gemini, or local Ollama)
Via Composer
composer require wortic/watp-sdk
Via Docker
docker pull ghcr.io/wortic/watp-node:latest
docker run -d \
--name watp-node \
-p 8090:8090 \
-v $(pwd)/.env:/app/.env \
ghcr.io/wortic/watp-node:latest
Message Format
All WATP communication uses a standardized JSON envelope. Each message references the previous hash, forming an immutable chain.
{
"protocol": "watp/1.0",
"id": "msg_01HZ3...",
"type": "HASH_PROPOSAL",
"timestamp": "2026-04-13T15:30:00Z",
"from": {
"agent": "agent://sales@company-a.watp",
"tax_id": "12.345.678/0001-90"
},
"to": {
"agent": "agent://procurement@company-b.watp",
"tax_id": "98.765.432/0001-10"
},
"payload": {
"items": [{ "description": "Cat6 Patch Cord 1.5m", "qty": 500, "unit_price": 4.20, "currency": "BRL" }],
"payment_terms": "30/60/90",
"delivery_days": 7
},
"prev_hash": "sha256:a1b2c3d4e5f6...",
"hash": "sha256:f9e8d7c6b5a4...",
"signature": "x509:RSA256:base64..."
}
State Machine
The lifecycle of a WATP negotiation follows deterministic states. Each transition is validated and persisted in the hash chain.
| State | Type | Description |
|---|---|---|
HASH_INTEREST |
Start | Agent detects demand and publishes a buy interest to the network |
HASH_PROPOSAL |
Negotiation | Formal proposal: price, payment terms, delivery |
HASH_COUNTER |
Negotiation | Counter-proposal within configured guardrails |
HASH_WAITING_HUMAN |
Safety | Outside parameters — human approval required |
HASH_CONCLUDED |
Final | Agreement signed with X.509 certificates |
HASH_CANCELLED |
Final | Negotiation cancelled by either party |
HASH_WAITING_HUMAN
This state is mandatory when the negotiation exceeds configured guardrails. The system never closes an agreement outside defined limits without explicit human approval.
Hash Chain
Each message contains the SHA-256 hash of the previous message, creating an immutable audit trail without requiring a blockchain.
use Wortic\WATP\HashChain;
$chain = new HashChain();
$hash = $chain->generate([
'type' => 'HASH_PROPOSAL',
'from' => 'agent://sales@my-company.watp',
'payload' => $payload,
'prev_hash' => $previousHash,
]);
$isValid = $chain->validate($negotiationHistory);
X.509 Signatures
To guarantee non-repudiation with legal validity, the HASH_CONCLUDED state is signed with X.509 digital certificates from both enterprises.
use Wortic\WATP\Signer;
$signer = new Signer('/path/to/certificate.pfx', 'password');
$signed = $signer->sign($concludedMessage);
$valid = $signer->verify($receivedMessage, $publicKey);
PHP SDK
The PHP SDK abstracts network communication, hash validation, and agent management.
<?php declare(strict_types: 1);
use Wortic\WATP\Node;
use Wortic\WATP\Config;
use Wortic\WATP\Agent\SalesAgent;
use Wortic\WATP\Agent\ProcurementAgent;
$config = Config::fromEnv(__DIR__ . '/.env');
$node = new Node($config);
$node->register(new SalesAgent($config));
$node->register(new ProcurementAgent($config));
$node->listen();
Configuration
All configuration is file-based via .env in the node directory.
# Identity
WATP_NODE_ID=my-company
WATP_TAX_ID=12.345.678/0001-90
# Legacy ERP connection
ERP_DSN=mysql://user:pass@localhost/erp_db
# AI Engine
AI_PROVIDER=openai # openai | anthropic | gemini | ollama
AI_API_KEY=sk-...
AI_MODEL=gpt-4o-mini
# Guardrails
GUARD_MIN_MARGIN=15
GUARD_MAX_DISCOUNT=20
GUARD_MAX_PAYMENT_DAYS=90
GUARD_AUTO_APPROVE_BELOW=5000
# X.509 Certificate
CERT_PATH=/certs/company.pfx
CERT_PASSWORD=certificate-password
Agents
Agents are PHP classes encapsulating business logic. Extend the base agent.
class MySalesAgent extends BaseAgent
{
public function handleInterest(Message $msg): ?Message
{
$product = $this->erp->semanticSearch($msg->payload['description']);
if (!$product) return null;
$price = $this->calculatePrice($product, $msg->payload['qty'], Guardrails::fromConfig());
return $this->propose($msg, [
'item' => $product->name, 'qty' => $msg->payload['qty'],
'unit_price' => $price, 'currency' => 'BRL',
]);
}
}
Guardrails
Immutable business rules constraining AI negotiations. If exceeded, state transitions to HASH_WAITING_HUMAN.
| Parameter | Type | Description |
|---|---|---|
GUARD_MIN_MARGIN |
int (%) | Minimum acceptable gross margin |
GUARD_MAX_DISCOUNT |
int (%) | Maximum discount over list price |
GUARD_MAX_PAYMENT_DAYS |
int | Maximum payment term in days |
GUARD_AUTO_APPROVE_BELOW |
float | Auto-approve below this total |
GUARD_MAX_ROUNDS |
int | Max counter-proposals before escalation |
GUARD_BLOCKED_IDS |
string | Comma-separated blocked tax IDs |
Products
The Product class provides typed access to the partner catalog with 18 enriched fields including dimensions, cost price, NCM code, and lead time.
use Wortic\WATP\Client;
use Wortic\WATP\Product;
$client = new Client(['node_url' => 'https://site-a.wortic.com/api']);
// List all products (returns Product[])
$products = $client->listProducts();
foreach ($products as $p) {
printf("%s — %s — R$ %.2f\n", $p->sku, $p->name, $p->price);
}
// Find a single product by SKU
$patch = $client->getProduct('PATCH-C6-1.5M');
if ($patch) {
echo $patch->brand; // "Furukawa"
echo $patch->weightKg; // 0.05
echo $patch->leadTimeDays; // 3
}
Product Fields
| Property | Type | Description |
|---|---|---|
name | string | Product name |
sku | string | Unique stock keeping unit |
price | float | List price |
costPrice | ?float | Cost price (margin calculation) |
category | ?string | Product category |
ncmCode | ?string | NCM fiscal code (Brazil) |
brand | ?string | Manufacturer brand |
weightKg | ?float | Weight in kilograms |
minOrderQty | ?int | Minimum order quantity |
leadTimeDays | ?int | Delivery lead time in days |
API Endpoints
The local node exposes a REST API for integration with external systems.
/api/v1/negotiate
Start a new negotiation by publishing HASH_INTEREST.
/api/v1/negotiations
List all active negotiations with current status.
/api/v1/negotiations/{id}
Full detail including the complete hash chain.
/api/v1/negotiations/{id}/approve
Human approval for HASH_WAITING_HUMAN state.
/api/v1/negotiations/{id}/cancel
Cancel a negotiation, generating HASH_CANCELLED.
/api/v1/health
Node health: status, uptime, registered agents.
/api/v1/catalog
Full product catalog with enriched fields (18 properties per product).
Webhooks
Configure webhooks to receive real-time events in your system.
{
"event": "negotiation.concluded",
"timestamp": "2026-04-13T15:45:00Z",
"data": {
"negotiation_id": "neg_01HZ3...",
"total_value": 2100.00,
"final_hash": "sha256:c4d5e6..."
},
"signature": "hmac-sha256:..."
}
Error Codes
| Code | Constant | Description |
|---|---|---|
| 4001 | INVALID_HASH_CHAIN |
Previous hash does not match |
| 4002 | GUARDRAIL_VIOLATED |
Proposal exceeded guardrails |
| 4003 | INVALID_SIGNATURE |
X.509 signature invalid or expired |
| 4004 | AGENT_NOT_FOUND |
Destination agent not on network |
| 4005 | NEGOTIATION_EXPIRED |
Negotiation TTL expired |
| 5001 | ERP_CONNECTION_FAILED |
Could not connect to local ERP |
| 5002 | AI_PROVIDER_ERROR |
Error calling AI provider API |
BYOK — Bring Your Own Key
Use your own API key. You control costs, model selection, and rate limits.
AI_PROVIDER=openai
AI_API_KEY=sk-proj-...
AI_MODEL=gpt-4o-mini
Local Edge Compute
Zero cost. The model runs on the client's own server, fully offline and private.
AI_PROVIDER=ollama
AI_OLLAMA_URL=http://localhost:11434
AI_MODEL=llama3.1:7b
Anti-Amnesia Orchestrator
Ensures the model never loses negotiation context or breaks JSON format. Automatically prunes history and re-injects the system prompt.
use Wortic\WATP\AI\Orchestrator;
$orchestrator = new Orchestrator([
'max_context_tokens' => 4096,
'prune_strategy' => 'keep_last_3_turns',
'force_json_output' => true,
'temperature' => 0.1,
]);
$response = $orchestrator->complete($negotiationCtx, $currentMsg);
Why Anti-Amnesia?
In extended negotiations (5+ rounds), smaller models lose initial context. The Orchestrator maintains a compressed summary plus the intact system prompt, ensuring consistency even with limited context windows.