Observed since 20 Oct, 21:26 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
Python SDK for agent portability, discovery and trust based on ERC-8004
Python SDK for agent portability, discovery and trust based on ERC-8004.
Agent0 is the SDK for agentic economies. It enables agents to register, advertise their capabilities and how to communicate with them, and give each other feedback and reputation signals. All this using blockchain infrastructure (ERC-8004) and decentralized storage, enabling permissionless discovery without relying on proprietary catalogues or intermediaries.
Agent0 SDK enables you to:
This release adds two major new capabilities to the Python SDK, aligned with the TypeScript SDK: x402 payment-required HTTP and A2A (Agent-to-Agent) messaging/task support.
sdk.request() now returns X402RequiredResponse on HTTP 402 instead of throwing, so callers can inspect payment requirements and continue with x402Payment.pay() or x402Payment.pay_first().Agent.messageA2A(), Agent.listTasks(), Agent.loadTask(), and sdk.createA2AClient(...) let you talk to A2A endpoints from either a loaded Agent or an AgentSummary.overrideRpcUrls support x402 payments and agent loading across multiple chains from one SDK instance.examples/x402_a2a_demo.py, expanded unit/live coverage, and updated public docs.For detailed changes, migration notes, and testing guidance, see release_notes/RELEASE_NOTES_1.7.0.md (and prior notes in release_notes/).
Bug reports & feedback: GitHub: Report issues | Telegram: Agent0 channel | Email: team@ag0.xyz
pip install agent0-sdk
To install a specific version explicitly:
pip install agent0-sdk==1.7.0
git clone https://github.com/agent0lab/agent0-py.git
cd agent0-py
pip install -e .
from agent0_sdk import SDK
import os
# Initialize SDK with IPFS and subgraph
sdk = SDK(
chainId=11155111, # Ethereum Sepolia testnet (use 1 for Ethereum Mainnet)
rpcUrl=os.getenv("RPC_URL"),
signer=os.getenv("PRIVATE_KEY"),
ipfs="pinata", # Options: "pinata", "filecoinPin", "node" (Kubo daemon)
pinataJwt=os.getenv("PINATA_JWT") # For Pinata
# Subgraph URL auto-defaults from DEFAULT_SUBGRAPH_URLS
)
# Create agent
agent = sdk.createAgent(
name="My AI Agent",
description="An intelligent assistant for various tasks. Skills: data analysis, code generation.",
image="https://example.com/agent-image.png"
)
# Configure endpoints (automatically extracts capabilities)
agent.setMCP("https://mcp.example.com/") # Extracts tools, prompts, resources
agent.setA2A("https://a2a.example.com/agent-card.json") # Extracts skills
agent.setENS("myagent.eth")
# Add OASF skills and domains (standardized taxonomies)
agent.addSkill("data_engineering/data_transformation_pipeline", validate_oasf=True)
agent.addSkill("natural_language_processing/natural_language_generation/summarization", validate_oasf=True)
agent.addDomain("finance_and_business/investment_services", validate_oasf=True)
agent.addDomain("technology/data_science/data_science", validate_oasf=True)
agent.setTrust(reputation=True, cryptoEconomic=True)
# Add metadata and set status
agent.setMetadata({"version": "1.0.0", "category": "ai-assistant"})
agent.setActive(True)
# Register on-chain with IPFS (submitted-by-default)
reg_tx = agent.registerIPFS()
reg = reg_tx.wait_confirmed(timeout=180).result
print(f"Agent registered: {reg.agentId}") # e.g., "11155111:123"
print(f"Agent URI: {reg.agentURI}") # e.g., "ipfs://Qm..."
# (Optional) Change the agent wallet after registration
# - On mint/registration, `agentWallet` defaults to the current owner address.
# - Call this only if you want a DIFFERENT wallet (or after a transfer, since the wallet resets to zero).
# - Transaction is sent by the SDK signer (agent owner), but the signature must be produced by the NEW wallet.
wallet_tx = agent.setWallet(
"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
chainId=11155111,
new_wallet_signer=os.getenv("NEW_WALLET_PRIVATE_KEY"),
)
if wallet_tx:
wallet_tx.wait_confirmed(timeout=180)
data: URI)ERC-8004 allows storing the entire registration JSON directly on-chain by setting agentURI/tokenURI to a base64 JSON data URI (e.g. data:application/json;base64,...).
# Register (or update) with a fully on-chain registration file (data URI)
tx = agent.registerOnChain()
reg = tx.wait_confirmed(timeout=180).result
print(f"Agent URI (on-chain data): {reg.agentURI}")
Notes:
SDK.loadAgent() enforces a default max decoded size of 256 KiB for data URIs. Override with:sdk = SDK(
chainId=11155111,
rpcUrl=os.getenv(\"RPC_URL\"),
signer=os.getenv(\"PRIVATE_KEY\"),
registrationDataUriMaxBytes=512 * 1024,
)
# Load existing agent for editing
agent = sdk.loadAgent("11155111:123") # Format: "chainId:agentId"
# Edit agent properties
agent.updateInfo(description="Updated description with new capabilities")
agent.setMCP("https://new-mcp.example.com/")
# Re-register to update on-chain
update_tx = agent.registerIPFS()
update = update_tx.wait_confirmed(timeout=180).result
print(f"Updated: {update.agentURI}")
# Search by name, capabilities, or attributes
results = sdk.searchAgents(
filters={
"name": "AI", # substring
"mcpTools": ["code_generation"],
"a2aSkills": ["python"],
"active": True,
"x402support": True,
"feedback": {"minValue": 80, "tag": "enterprise", "includeRevoked": False},
},
options={"sort": ["updatedAt:desc"]},
)
for agent in results:
print(f"{agent.name}: {agent.description}")
print(f" Tools: {agent.mcpTools}")
print(f" Skills: {agent.a2aSkills}")
# Get single agent (read-only, faster)
agent_summary = sdk.getAgent("11155111:123")
# On-chain-only feedback (no off-chain upload, even if IPFS is configured)
tx = sdk.giveFeedback(
agentId="11155111:123",
value=85, # number|string
tag1="data_analyst", # Optional: tags are strings
tag2="finance",
endpoint="https://example.com/endpoint", # Optional: saved on-chain
)
feedback = tx.wait_confirmed(timeout=180).result
# Rich feedback (optional off-chain file + on-chain fields)
feedback_file = sdk.prepareFeedbackFile({
"mcpTool": "code_generation", # Spec-aligned MCP tool identifier
"a2aSkills": ["python"], # Spec-aligned A2A skills
"a2aContextId": "session:abc", # Optional
"text": "Great agent!", # Optional
})
tx = sdk.giveFeedback(
agentId="11155111:123",
value=85,
tag1="data_analyst",
tag2="finance",
endpoint="https://example.com/endpoint",
feedbackFile=feedback_file, # If provided, requires IPFS configured
)
feedback = tx.wait_confirmed(timeout=180).result
# Search feedback
results = sdk.searchFeedback(
agentId="11155111:123",
capabilities=["code_generation"], # capabilities filters by feedbackFile.mcpTool
minValue=80,
maxValue=100
)
# NEW: Search feedback given by a reviewer wallet (across all agents; subgraph required)
given = sdk.searchFeedback(
reviewers=["0x742d35cc6634c0532925a3b844bc9e7595f0beb7"]
)
# NEW: Search feedback across multiple agents at once
multi = sdk.searchFeedback(
agents=["11155111:123", "11155111:456", "11155111:789"]
)
# Get reputation summary
summary = sdk.getReputationSummary("11155111:123")
print(f"Average value: {summary['averageValue']}")
# Option 1: Filecoin Pin (free for ERC-8004 agents)
sdk = SDK(
chainId=11155111,
rpcUrl="...",
signer=private_key,
ipfs="filecoinPin",
filecoinPrivateKey="your-filecoin-private-key"
)
# Option 2: IPFS Node
sdk = SDK(
chainId=11155111,
rpcUrl="...",
signer=private_key,
ipfs="node",
ipfsNodeUrl="https://ipfs.infura.io:5001"
)
# Option 3: Pinata (free for ERC-8004 agents)
sdk = SDK(
chainId=11155111,
rpcUrl="...",
signer=private_key,
ipfs="pinata",
pinataJwt="your-pinata-jwt-token"
)
# Option 4: HTTP registration (no IPFS)
sdk = SDK(chainId=11155111, rpcUrl="...", signer=private_key)
agent.register("https://example.com/agent-registration.json")
The SDK includes support for the Open Agentic Schema Framework (OASF) taxonomies, enabling agents to advertise standardized skills and domains. This improves discoverability and interoperability across agent platforms.
# Add OASF skills (with optional validation)
agent.addSkill("advanced_reasoning_planning/strategic_planning", validate_oasf=True)
agent.addSkill("data_engineering/data_transformation_pipeline", validate_oasf=True)
# Add OASF domains (with optional validation)
agent.addDomain("finance_and_business/investment_services", validate_oasf=True)
agent.addDomain("technology/data_science/data_visualization", validate_oasf=True)
# Remove skills/domains
agent.removeSkill("old_skill")
agent.removeDomain("old_domain")
OASF skills and domains appear in your agent's registration file:
{
"endpoints": [
{
"name": "OASF",
"endpoint": "https://github.com/agntcy/oasf/",
"version": "0.8",
"skills": [
"advanced_reasoning_planning/strategic_planning",
"data_engineering/data_transformation_pipeline"
],
"domains": [
"finance_and_business/investment_services",
"technology/data_science/data_science"
]
}
]
}
The SDK includes complete OASF v0.8.0 taxonomy files:
agent0_sdk/taxonomies/all_skills.json (136 skills)agent0_sdk/taxonomies/all_domains.json (204 domains)Browse these files to find appropriate skill and domain slugs. For more information, see the OASF specification and Release Notes v0.31.
The unified search API is:
results = sdk.searchAgents(filters: dict | SearchFilters | None = None, options: dict | SearchOptions | None = None)
# results: list[AgentSummary]
FeedbackFilters (used as filters["feedback"])@dataclass
class FeedbackFilters:
hasFeedback: Optional[bool] = None
hasNoFeedback: Optional[bool] = None
includeRevoked: Optional[bool] = None
minValue: Optional[float] = None
maxValue: Optional[float] = None
minCount: Optional[int] = None
maxCount: Optional[int] = None
fromReviewers: Optional[List[Address]] = None
endpoint: Optional[str] = None # substring match
hasResponse: Optional[bool] = None
tag1: Optional[str] = None
tag2: Optional[str] = None
tag: Optional[str] = None # matches tag1 OR tag2
| Field | Semantics |
|---|---|
hasFeedback / hasNoFeedback | Filter by whether the agent has any feedback |
includeRevoked | Include revoked feedback entries in the pool used for filtering |
minValue / maxValue | Threshold on average value over feedback matching the other feedback constraints (inclusive) |
minCount / maxCount | Threshold on count over feedback matching the other feedback constraints (inclusive) |
fromReviewers | Only consider feedback from these reviewer wallets |
endpoint | Only consider feedback whose endpoint contains this substring |
hasResponse | Only consider feedback that has at least one response (if supported) |
tag1 / tag2 | Only consider feedback matching tag1/tag2 |
tag | Shorthand: match either tag1 OR tag2 |
SearchFiltersDateLike = Union[datetime, str, int]
@dataclass
class SearchFilters:
chains: Optional[Union[List[ChainId], Literal["all"]]] = None
agentIds: Optional[List[AgentId]] = None
name: Optional[str] = None
description: Optional[str] = None
owners: Optional[List[Address]] = None
operators: Optional[List[Address]] = None
hasRegistrationFile: Optional[bool] = None
hasWeb: Optional[bool] = None
hasMCP: Optional[bool] = None
hasA2A: Optional[bool] = None
hasOASF: Optional[bool] = None
hasEndpoints: Optional[bool] = None
webContains: Optional[str] = None
mcpContains: Optional[str] = None
a2aContains: Optional[str] = None
ensContains: Optional[str] = None
didContains: Optional[str] = None
walletAddress: Optional[Address] = None
supportedTrust: Optional[List[str]] = None
a2aSkills: Optional[List[str]] = None
mcpTools: Optional[List[str]] = None
mcpPrompts: Optional[List[str]] = None
mcpResources: Optional[List[str]] = None
oasfSkills: Optional[List[str]] = None
oasfDomains: Optional[List[str]] = None
active: Optional[bool] = None
x402support: Optional[bool] = None
registeredAtFrom: Optional[DateLike] = None
registeredAtTo: Optional[DateLike] = None
updatedAtFrom: Optional[DateLike] = None
updatedAtTo: Optional[DateLike] = None
hasMetadataKey: Optional[str] = None
metadataValue: Optional[Dict[str, str]] = None # { key, value }
keyword: Optional[str] = None
feedback: Optional[FeedbackFilters] = None
SearchOptions@dataclass
class SearchOptions:
sort: Optional[List[str]] = None
semanticMinScore: Optional[float] = None
semanticTopK: Optional[int] = None
AgentSummary (returned items)@dataclass
class AgentSummary:
chainId: ChainId
agentId: AgentId
name: str
image: Optional[URI]
description: str
owners: List[Address]
operators: List[Address]
# Endpoint strings (present when advertised; not booleans)
mcp: Optional[str] = None
a2a: Optional[str] = None
web: Optional[str] = None
email: Optional[str] = None
ens: Optional[str] = None
did: Optional[str] = None
walletAddress: Optional[Address] = None
supportedTrusts: List[str] = field(default_factory=list)
a2aSkills: List[str] = field(default_factory=list)
mcpTools: List[str] = field(default_factory=list)
mcpPrompts: List[str] = field(default_factory=list)
mcpResources: List[str] = field(default_factory=list)
oasfSkills: List[str] = field(default_factory=list)
oasfDomains: List[str] = field(default_factory=list)
active: bool = False
x402support: bool = False
createdAt: Optional[int] = None
updatedAt: Optional[int] = None
lastActivity: Optional[int] = None
agentURI: Optional[str] = None
agentURIType: Optional[str] = None
feedbackCount: Optional[int] = None
averageValue: Optional[float] = None
semanticScore: Optional[float] = None
extras: Dict[str, Any] = field(default_factory=dict)
Complete working examples are available in the tests/ directory:
test_registration.py - Agent registration with HTTP URItest_registrationIpfs.py - Agent registration with IPFStest_feedback.py - Complete feedback flow with IPFS storagetest_search.py - Agent search and discoverytest_transfer.py - Agent ownership transfertest_oasf_management.py - OASF skills/domains management (unit tests)test_real_public_servers.py - Endpoint crawler against real public MCP/A2A serverstest_multi_chain.py - Multi-chain read-only operations (subgraph-based)Full documentation is available at sdk.ag0.xyz, including:
Agent0 SDK is MIT-licensed public good brought to you by Marco De Rossi in collaboration with Consensys, 🦊 MetaMask and Agent0, Inc. We are looking for co-maintainers. Please reach out if you want to help.
Thanks also to Edge & Node (The Graph), Protocol Labs and Pinata for their support.
Download counts and popularity will appear here as the collector receives them.
| Version | Published | Direct dependencies | Open version |
|---|---|---|---|
| 1.7.1 | 16 Mar 2026 | 18 |
This describes our collected data; it is not a security assessment.
Observed since 20 Oct, 21:26 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package:c209fe0d4842b46be2b7c8fc597434a181977f238c68f8045574d9eb73d68444