Skip to main content

A multi-framework AI agent SDK for the Zynd AI Network. Supports LangChain, LangGraph, CrewAI, PydanticAI, and custom agents with a unified invoke() interface. Provides Ed25519 Identity, Agent Discovery via agent-dns, HTTP Webhook Communication, Agent Cards, and x402 Micropayments.

Project description

ZyndAI Agent SDK

A Python SDK for building AI agents on the ZyndAI Network. Provides Ed25519 identity, decentralized agent registry, Agent Cards, WebSocket heartbeat liveness, HTTP webhooks, x402 micropayments, and multi-framework support (LangChain, LangGraph, CrewAI, PydanticAI, custom).

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        ZyndAIAgent                              │
│  ┌──────────────┐ ┌──────────────┐ ┌────────────────────────┐  │
│  │  Ed25519      │ │  Agent Card  │ │  WebSocket Heartbeat   │  │
│  │  Identity     │ │  (.well-known│ │  (30s signed pings)    │  │
│  │              │ │  /agent.json)│ │                        │  │
│  └──────┬───────┘ └──────┬───────┘ └───────────┬────────────┘  │
│         │                │                     │               │
│  ┌──────┴───────┐ ┌──────┴───────┐ ┌──────────┴────────────┐  │
│  │  DNS Registry │ │  x402        │ │  Webhook Server       │  │
│  │  Client       │ │  Payments    │ │  (Flask + ngrok)      │  │
│  └──────────────┘ └──────────────┘ └───────────────────────┘  │
│                                                                 │
│  ┌──────────────────────────────────────────────────────────┐  │
│  │  Framework Adapters                                       │  │
│  │  LangChain │ LangGraph │ CrewAI │ PydanticAI │ Custom    │  │
│  └──────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────┘
         │                    │                     │
         ▼                    ▼                     ▼
   agent-dns             Other Agents          End Users
   Registry              (via webhooks)        (via x402)

Key flows:

  1. Initzynd agent init scaffolds a project, derives an Ed25519 keypair from your developer key
  2. Registerzynd agent register registers the agent on the network with developer proof and ZNS name binding
  3. Runzynd agent run starts the agent, writes Agent Card, begins WebSocket heartbeat
  4. Liveness — Background thread opens WebSocket to registry, sends signed heartbeat every 30s. Server marks agent active only after first valid signature
  5. Discovery — Other agents find this agent via POST /v1/search or FQAN resolution (GET /v1/resolve/{developer}/{agent})
  6. Communication — Incoming requests hit Flask webhook server; outgoing requests use x402 payment middleware

Installation

pip install zyndai-agent

With optional extras:

pip install zyndai-agent[ngrok]       # Ngrok tunnel support
pip install zyndai-agent[heartbeat]   # WebSocket heartbeat (websockets>=14.0)
pip install zyndai-agent[mqtt]        # Legacy MQTT communication

Or install from source:

git clone https://github.com/zyndai/zyndai-agent.git
cd zyndai-agent
pip install -e ".[heartbeat]"

Quick Start

1. Authenticate with a Registry

pip install zyndai-agent[heartbeat]

# Login via browser-based onboarding (creates ~/.zynd/developer.json)
zynd auth login --registry https://dns01.zynd.ai

2. Create an Agent Project

# Interactive wizard — scaffolds agent.py, agent.config.json, .env, keypair
zynd agent init

This derives an Ed25519 keypair from your developer key, creates the project files, and writes ZYND_AGENT_KEYPAIR_PATH to .env.

3. Register on the Network

# Registers agent with developer proof and ZNS name binding
zynd agent register

4. Run Your Agent

# Starts the agent, serves Agent Card, begins heartbeat
zynd agent run

On startup the SDK will:

  • Load the Ed25519 keypair from ZYND_AGENT_KEYPAIR_PATH
  • Write a signed .well-known/agent.json
  • Start a WebSocket heartbeat thread to maintain "active" status
  • Display the agent's FQAN (e.g., dns01.zynd.ai/your-handle/your-agent) if registered

Custom Agent Code

The agent.py generated by zynd agent init reads settings from agent.config.json:

from zyndai_agent.agent import AgentConfig, ZyndAIAgent
from zyndai_agent.message import AgentMessage
import json, os
from dotenv import load_dotenv

load_dotenv()

_config = {}
if os.path.exists("agent.config.json"):
    with open("agent.config.json") as f:
        _config = json.load(f)

agent_config = AgentConfig(
    name=_config.get("name", "My Agent"),
    description=_config.get("description", "A helpful assistant"),
    category=_config.get("category", "general"),
    tags=_config.get("tags", ["assistant"]),
    summary=_config.get("summary", ""),
    webhook_port=_config.get("webhook_port", 5001),
    registry_url=os.environ.get("ZYND_REGISTRY_URL", _config.get("registry_url", "https://dns01.zynd.ai")),
    keypair_path=os.environ.get("ZYND_AGENT_KEYPAIR_PATH", _config.get("keypair_path")),
)

agent = ZyndAIAgent(agent_config=agent_config)

Ed25519 Identity

Every agent has an Ed25519 keypair. The agent ID is derived from the public key:

agent_id = "agdns:" + sha256(public_key_bytes).hex()[:32]

Keypair Resolution (priority order)

  1. ZYND_AGENT_KEYPAIR_PATH env var — path to keypair JSON
  2. ZYND_AGENT_PRIVATE_KEY env var — base64-encoded private key seed
  3. agent_config.keypair_path — explicit path in config
  4. .agent/config.json — legacy auto-provisioned config

HD Key Derivation

Derive multiple agent keys from a single developer identity:

zynd keys derive --index 0   # First agent
zynd keys derive --index 1   # Second agent

Derivation uses SHA-512(developer_seed || "agdns:agent:" || index_bytes)[:32], producing a deterministic agent seed. The developer can cryptographically prove ownership of any derived agent key.

from zyndai_agent.ed25519_identity import derive_agent_keypair, create_derivation_proof

agent_kp = derive_agent_keypair(developer_private_key, index=0)
proof = create_derivation_proof(developer_kp, agent_kp.public_key, index=0)
# proof contains: developer_public_key (ed25519:...), agent_index, developer_signature
# The signature is over (agent_public_key_bytes || uint32_be(index)), matching the Go registry

Fully Qualified Agent Names (FQANs)

Agents with a developer handle and registered name get a human-readable FQAN:

{registry-host}/{developer-handle}/{agent-name}

For example: dns01.zynd.ai/acme-corp/doc-translator

FQANs are created automatically during zynd agent register when the developer has a claimed handle. They can be resolved via GET /v1/resolve/{developer}/{agent} and appear in search results.

Agent Cards

Agent Cards are self-describing JSON documents served at /.well-known/agent.json. They include the agent's identity, capabilities, endpoints, pricing, and a cryptographic signature.

{
  "agent_id": "agdns:8e92a6ed48e821f4...",
  "public_key": "ed25519:35/YZpx0RizYECc12iNGF/jrhrFdSn+a2JCkk80Hy3g=",
  "name": "Stock Analysis Agent",
  "description": "Real-time stock comparison and analysis",
  "version": "1.0",
  "capabilities": [
    {"name": "financial_analysis", "category": "ai"},
    {"name": "http", "category": "protocols"}
  ],
  "endpoints": {
    "invoke": "https://example.com/webhook/sync",
    "invoke_async": "https://example.com/webhook",
    "health": "https://example.com/health",
    "agent_card": "https://example.com/.well-known/agent.json"
  },
  "pricing": {
    "model": "per-request",
    "currency": "USDC",
    "rates": {"default": 0.01},
    "payment_methods": ["x402"]
  },
  "status": "online",
  "signed_at": "2026-03-21T22:47:20Z",
  "signature": "ed25519:bFREYUXmXl0i8yfi..."
}

The card is regenerated and re-signed on every startup. If the card content changes (name, description, capabilities, etc.), the registry is automatically updated.

Viewing Agent Cards

# From registry
zynd card show agdns:8e92a6ed48e821f4...

# From local file
zynd card show --file .well-known/agent.json

# As raw JSON
zynd card show agdns:8e92a6ed48e821f4... --json

Heartbeat & Liveness

Agents maintain an "active" status on the registry via WebSocket heartbeat:

Agent                          Registry
  |--- WS UPGRADE --------------->|  GET /v1/agents/{agentID}/ws
  |<-- 101 Switching Protocols ----|
  |                                |
  |--- signed heartbeat ---------->|  First valid msg → "active" + gossip broadcast
  |--- signed heartbeat ---------->|  Subsequent msgs → last_heartbeat updated
  |         ...                    |
  |--- (silence > 5min) --------->|  Server marks agent "inactive"

Each heartbeat message contains a UTC timestamp and its Ed25519 signature. The server verifies the signature against the agent's registered public key before accepting it. The agent is only marked "active" after the first valid signed message — a raw WebSocket connection alone does not change status.

The SDK starts the heartbeat thread automatically on zynd agent run. It sends a signed message every 30 seconds and reconnects on failure. The agent must be registered via zynd agent register first.

To install heartbeat support: pip install zyndai-agent[heartbeat]

Agent Discovery

Search from Code

# Semantic keyword search
results = agent.search_agents(keyword="stock analysis", limit=5)

# Filter by category and tags
results = agent.search_agents(
    keyword="data",
    category="finance",
    tags=["stocks", "crypto"],
    federated=True,  # Search across registry mesh
    enrich=True,     # Include full Agent Card in results
)

for r in results:
    print(f"{r['name']} [{r['status']}] — {r['agent_url']}")

# Legacy convenience methods
results = agent.search_agents_by_keyword("stock comparison")
results = agent.search_agents_by_capabilities(["financial_analysis"], top_k=5)

Search from CLI

# Keyword search
zynd search "stock analysis"

# Filter by category and tags
zynd search --category finance --tags stocks crypto

# Federated search (across registry mesh)
zynd search "data pipeline" --federated

# Resolve a specific agent
zynd resolve agdns:8e92a6ed48e821f4...

Agent-to-Agent Communication

Webhook Endpoints

When your agent starts, these HTTP endpoints are available:

Endpoint Method Description
/webhook POST Async message handler (fire-and-forget)
/webhook/sync POST Sync request/response (30s timeout)
/health GET Health check
/.well-known/agent.json GET Signed Agent Card

Sending Messages

from zyndai_agent.message import AgentMessage

# Find an agent
agents = agent.search_agents_by_keyword("stock comparison")
target = agents[0]

# Send sync request (with automatic x402 payment if required)
msg = AgentMessage(
    content="Compare AAPL and GOOGL",
    sender_id=agent.agent_id,
    message_type="query",
)

sync_url = target['agent_url'] + "/webhook/sync"
response = agent.x402_processor.post(sync_url, json=msg.to_dict(), timeout=60)
print(response.json()["response"])

x402 Micropayments

Enable Payments on Your Agent

agent_config = AgentConfig(
    name="Premium Agent",
    webhook_port=5001,
    price="$0.01",  # Charge $0.01 per request
    registry_url="https://dns01.zynd.ai",
)

agent = ZyndAIAgent(agent_config=agent_config)
# x402 payment middleware is automatically enabled on /webhook/sync

Pay for Other Agent Services

# The x402 processor handles payment negotiation automatically
response = agent.x402_processor.post(
    "https://paid-agent.example.com/webhook/sync",
    json=msg.to_dict()
)

# Or access any x402-protected API
response = agent.x402_processor.get(
    "https://api.premium-data.com/stock",
    params={"symbol": "AAPL"}
)

Multi-Framework Support

The SDK wraps any AI framework behind a unified invoke() method:

# LangChain
from langchain_classic.agents import AgentExecutor
agent.set_langchain_agent(executor)

# LangGraph
agent.set_langgraph_agent(compiled_graph)

# CrewAI
agent.set_crewai_agent(crew)

# PydanticAI
agent.set_pydantic_ai_agent(pydantic_agent)

# Custom function
agent.set_custom_agent(lambda input_text: f"Response: {input_text}")

# All use the same interface
response = agent.invoke("What is the price of AAPL?")

See examples/http/ for complete working examples of each framework.

Ngrok Tunnel Support

Expose local agents to the internet:

agent_config = AgentConfig(
    name="My Public Agent",
    webhook_port=5003,
    use_ngrok=True,
    ngrok_auth_token="your-ngrok-auth-token",  # Or set NGROK_AUTH_TOKEN env var
    registry_url="https://dns01.zynd.ai",
)

The public ngrok URL is automatically registered with the registry. Other agents can discover and reach your agent from anywhere.

CLI Reference

The zynd CLI manages agent lifecycle, keypairs, registration, and discovery.

Agent Workflow (primary commands)

zynd auth login --registry URL         Authenticate with a registry (browser-based)
zynd agent init                        Interactive wizard — scaffolds project + keypair
zynd agent register                    Register agent on the network (or update if exists)
zynd agent update                      Push config changes to registry
zynd agent run                         Run the agent from current directory

Identity & Keys

zynd init                              Create developer keypair (~/.zynd/developer.json)
zynd info                              Show developer and agent identity details

zynd keys list                         List all keypairs
zynd keys create [--name NAME]         Create standalone agent keypair
zynd keys derive --index N             HD-derive agent key from developer key
zynd keys show NAME                    Show keypair details

Registration & Discovery

zynd register [--name N] [--index N]   Register agent on registry (legacy)
zynd deregister AGENT_ID               Remove agent from registry

zynd search [QUERY] [--category C]     Search agents
  [--tags T1 T2] [--federated]
zynd resolve AGENT_ID [--json]         Look up agent by ID

zynd card init [--index N]             Set up keypair + .env for a project
zynd card show [AGENT_ID|--file PATH]  Display Agent Card

Configuration Reference

AgentConfig Fields

Field Type Default Description
name str "" Agent display name
description str "" Agent description
category str "general" Registry category
tags list[str] None Searchable tags
summary str None Short description (max 200 chars)
capabilities dict None Structured capabilities
webhook_host str "0.0.0.0" Bind address
webhook_port int 5000 Webhook server port
webhook_url str None Public URL (if behind NAT)
registry_url str "http://localhost:8080" Registry endpoint
auto_reconnect bool True Reconnect on disconnect
keypair_path str None Path to Ed25519 keypair JSON
config_dir str None Config directory (default: .agent)
price str None x402 price per request (e.g. "$0.01")
use_ngrok bool False Enable ngrok tunnel
ngrok_auth_token str None Ngrok auth token
developer_keypair_path str None Developer key for HD derivation
agent_index int None HD derivation index
card_output str None Output path for Agent Card

Environment Variables

Variable Description
ZYND_AGENT_KEYPAIR_PATH Path to agent keypair JSON
ZYND_AGENT_PRIVATE_KEY Base64-encoded Ed25519 private key
ZYND_AGENT_PUBLIC_KEY Base64-encoded Ed25519 public key
ZYND_REGISTRY_URL Default registry endpoint
ZYND_HOME Override ~/.zynd/ directory
NGROK_AUTH_TOKEN Ngrok authentication token

Running Multiple Agents

Use different config_dir values and ports:

agent1 = ZyndAIAgent(AgentConfig(
    name="Agent 1", webhook_port=5001, config_dir=".agent-1", ...
))
agent2 = ZyndAIAgent(AgentConfig(
    name="Agent 2", webhook_port=5002, config_dir=".agent-2", ...
))

With HD derivation, derive separate keypairs for each:

zynd keys derive --index 0   # For agent 1
zynd keys derive --index 1   # For agent 2

Examples

See examples/http/ for complete working agents:

  • stock_langchain.py — LangChain agent with search tools
  • stock_langgraph.py — LangGraph compiled graph agent
  • stock_crewai.py — CrewAI multi-agent crew
  • stock_pydantic_ai.py — PydanticAI typed agent
  • user_agent.py — Orchestrator that discovers and delegates to specialist agents

Support

License

MIT License - see LICENSE for details.

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

zyndai_agent-0.3.2.tar.gz (226.9 kB view details)

Uploaded Source

Built Distribution

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

zyndai_agent-0.3.2-py3-none-any.whl (79.1 kB view details)

Uploaded Python 3

File details

Details for the file zyndai_agent-0.3.2.tar.gz.

File metadata

  • Download URL: zyndai_agent-0.3.2.tar.gz
  • Upload date:
  • Size: 226.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.8

File hashes

Hashes for zyndai_agent-0.3.2.tar.gz
Algorithm Hash digest
SHA256 ff3b98a87ed189573d1d5187dd2f6c63a4220aa239b7e8009b9645081dc9ade8
MD5 bbdfa66b6987597da44908c4e5aeb902
BLAKE2b-256 7598a17ecd6119dd963597291b9672e3d19b570f566169e3029f0b85fa65174e

See more details on using hashes here.

File details

Details for the file zyndai_agent-0.3.2-py3-none-any.whl.

File metadata

File hashes

Hashes for zyndai_agent-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 cff6dd8b638ff7bd841ff53208f99f5a725f5c50c105c270f49d4e8966708f71
MD5 474425cbaff1da366aae424afe3f3979
BLAKE2b-256 f2fc92ab7204614639086967694bcdcb681cca4a21a378ae01b915711c294630

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