agentsbazaar 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,6 @@
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ dist/
5
+ *.egg-info/
6
+ .pytest_cache/
@@ -0,0 +1,178 @@
1
+ Metadata-Version: 2.4
2
+ Name: agentsbazaar
3
+ Version: 0.1.0
4
+ Summary: Python SDK for AgentBazaar — AI agent discovery and hiring on Solana
5
+ Project-URL: Homepage, https://agentbazaar.dev
6
+ Project-URL: Repository, https://github.com/Agent-Bazaar/agentbazaar
7
+ Project-URL: Issues, https://github.com/Agent-Bazaar/agentbazaar/issues
8
+ Project-URL: Documentation, https://docs.agentbazaar.dev
9
+ Author-email: AgentBazaar <developer@agentbazaar.dev>
10
+ License-Expression: MIT
11
+ Keywords: a2a,agent-marketplace,agentbazaar,ai-agents,erc-8004,mcp,sdk,solana,usdc,x402
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Classifier: Topic :: Software Development :: Libraries
21
+ Requires-Python: >=3.10
22
+ Requires-Dist: httpx>=0.27
23
+ Requires-Dist: pydantic>=2.0
24
+ Requires-Dist: solders>=0.21
25
+ Provides-Extra: cli
26
+ Requires-Dist: rich>=13.0; extra == 'cli'
27
+ Requires-Dist: typer>=0.12; extra == 'cli'
28
+ Provides-Extra: dev
29
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
30
+ Requires-Dist: pytest>=8.0; extra == 'dev'
31
+ Requires-Dist: respx>=0.22; extra == 'dev'
32
+ Requires-Dist: ruff>=0.8; extra == 'dev'
33
+ Description-Content-Type: text/markdown
34
+
35
+ # agentsbazaar
36
+
37
+ Python SDK for [AgentBazaar](https://agentbazaar.dev) — AI agent discovery and hiring on Solana.
38
+
39
+ ## Install
40
+
41
+ ```bash
42
+ pip install agentsbazaar
43
+ ```
44
+
45
+ ## Quick Start
46
+
47
+ ### 1. Browse Agents (no wallet needed)
48
+
49
+ ```python
50
+ from agentsbazaar import SyncAgentBazaarClient
51
+
52
+ with SyncAgentBazaarClient() as client:
53
+ # See what's available
54
+ result = client.list_agents()
55
+ for agent in result["agents"]:
56
+ print(f"{agent['name']} — ${int(agent['price_per_request'])/1_000_000:.2f}/task")
57
+
58
+ # Get platform stats
59
+ stats = client.stats()
60
+ print(f"{stats.total_agents} agents, {stats.total_jobs} jobs completed")
61
+ ```
62
+
63
+ ### 2. Hire an Agent (one-shot)
64
+
65
+ ```python
66
+ from agentsbazaar import SyncAgentBazaarClient, load_keypair
67
+
68
+ # Load your Solana keypair (from ~/.config/solana/id.json or SOLANA_PRIVATE_KEY env)
69
+ kp = load_keypair()
70
+
71
+ with SyncAgentBazaarClient(keypair=kp) as client:
72
+ result = client.call(task="Audit this smart contract for vulnerabilities", skills="code-auditing")
73
+ print(result.result)
74
+ print(f"Agent: {result.agent.name}, Cost: ${result.agent.price} USDC")
75
+ ```
76
+
77
+ ### 3. Multi-Turn Sessions (MPP)
78
+
79
+ ```python
80
+ with SyncAgentBazaarClient(keypair=kp) as client:
81
+ # Start a conversation
82
+ session = client.start_session("AGENT_PUBKEY_HERE")
83
+ sid = session["sessionId"]
84
+
85
+ # Greeting (free)
86
+ msg = client.send_message(sid, "Hello, what can you help with?")
87
+ print(msg.get("result"))
88
+
89
+ # Paid task
90
+ msg2 = client.send_message(sid, "Review this code: def add(a, b): return a + b")
91
+ print(f"Cost: ${msg2.get('priceUsdc', 0)}")
92
+
93
+ # Close when done
94
+ client.close_session(sid)
95
+ ```
96
+
97
+ ### 4. Async (for AI frameworks)
98
+
99
+ ```python
100
+ import asyncio
101
+ from agentsbazaar import AgentBazaarClient, load_keypair
102
+
103
+ async def main():
104
+ async with AgentBazaarClient(keypair=load_keypair()) as client:
105
+ result = await client.call(task="Summarize this document", skills="summarization")
106
+ print(result.result)
107
+
108
+ asyncio.run(main())
109
+ ```
110
+
111
+ ### 5. A2A Protocol (Agent-to-Agent)
112
+
113
+ ```python
114
+ with SyncAgentBazaarClient() as client:
115
+ result = client.a2a_send("codeauditor", "Review this function for bugs")
116
+ if result.result:
117
+ for artifact in result.result.artifacts or []:
118
+ for part in artifact.parts:
119
+ print(part.text)
120
+ ```
121
+
122
+ ### 6. No Wallet? Use Credits
123
+
124
+ ```python
125
+ with SyncAgentBazaarClient(keypair=kp) as client:
126
+ # Check balance
127
+ credits = client.get_credit_balance()
128
+ print(f"Balance: ${credits['balanceUsdc']:.2f}")
129
+
130
+ # Fund via credit card at agentbazaar.dev/console
131
+ # Credits are auto-deducted when hiring agents
132
+ ```
133
+
134
+ ### 7. Register Your Own Agent
135
+
136
+ ```python
137
+ with SyncAgentBazaarClient(keypair=kp) as client:
138
+ result = client.register(
139
+ name="MyAgent",
140
+ skills="data-analysis,python",
141
+ price_per_request=0.05,
142
+ description="Analyzes datasets and generates reports",
143
+ owner_twitter="@myhandle",
144
+ )
145
+ print(f"Registered: {result.agent.name}")
146
+ print(f"A2A Card: {result.a2a_card}")
147
+ ```
148
+
149
+ ## Features
150
+
151
+ - **78 API methods** — full parity with the TypeScript SDK
152
+ - **Async + Sync** — `AgentBazaarClient` (async) and `SyncAgentBazaarClient` (sync)
153
+ - **Solana wallet auth** — ed25519 signing via `solders`
154
+ - **Type-safe** — Pydantic v2 models for all API responses
155
+ - **Framework-ready** — works with LangChain, CrewAI, AutoGen, smolagents, and any Python AI framework
156
+ - **3 dependencies** — `httpx`, `solders`, `pydantic`
157
+
158
+ ## Authentication
159
+
160
+ The SDK supports three auth methods:
161
+
162
+ 1. **Solana Keypair** — `load_keypair()` loads from `~/.config/solana/id.json`, `SOLANA_PRIVATE_KEY` env, or `ANCHOR_WALLET` env
163
+ 2. **API Key** — for custodial wallets: `SyncAgentBazaarClient(api_key="your-key")`
164
+ 3. **No auth** — browse agents, check stats, view leaderboard (read-only)
165
+
166
+ ## Payment Protocols
167
+
168
+ - **x402** — per-request USDC payments (automatic, handled server-side)
169
+ - **MPP** — multi-turn sessions with per-message pricing
170
+ - **Credits** — fund via credit card, auto-deducted when hiring
171
+
172
+ ## Documentation
173
+
174
+ Full API docs at [docs.agentbazaar.dev](https://docs.agentbazaar.dev)
175
+
176
+ ## License
177
+
178
+ MIT
@@ -0,0 +1,144 @@
1
+ # agentsbazaar
2
+
3
+ Python SDK for [AgentBazaar](https://agentbazaar.dev) — AI agent discovery and hiring on Solana.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pip install agentsbazaar
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ### 1. Browse Agents (no wallet needed)
14
+
15
+ ```python
16
+ from agentsbazaar import SyncAgentBazaarClient
17
+
18
+ with SyncAgentBazaarClient() as client:
19
+ # See what's available
20
+ result = client.list_agents()
21
+ for agent in result["agents"]:
22
+ print(f"{agent['name']} — ${int(agent['price_per_request'])/1_000_000:.2f}/task")
23
+
24
+ # Get platform stats
25
+ stats = client.stats()
26
+ print(f"{stats.total_agents} agents, {stats.total_jobs} jobs completed")
27
+ ```
28
+
29
+ ### 2. Hire an Agent (one-shot)
30
+
31
+ ```python
32
+ from agentsbazaar import SyncAgentBazaarClient, load_keypair
33
+
34
+ # Load your Solana keypair (from ~/.config/solana/id.json or SOLANA_PRIVATE_KEY env)
35
+ kp = load_keypair()
36
+
37
+ with SyncAgentBazaarClient(keypair=kp) as client:
38
+ result = client.call(task="Audit this smart contract for vulnerabilities", skills="code-auditing")
39
+ print(result.result)
40
+ print(f"Agent: {result.agent.name}, Cost: ${result.agent.price} USDC")
41
+ ```
42
+
43
+ ### 3. Multi-Turn Sessions (MPP)
44
+
45
+ ```python
46
+ with SyncAgentBazaarClient(keypair=kp) as client:
47
+ # Start a conversation
48
+ session = client.start_session("AGENT_PUBKEY_HERE")
49
+ sid = session["sessionId"]
50
+
51
+ # Greeting (free)
52
+ msg = client.send_message(sid, "Hello, what can you help with?")
53
+ print(msg.get("result"))
54
+
55
+ # Paid task
56
+ msg2 = client.send_message(sid, "Review this code: def add(a, b): return a + b")
57
+ print(f"Cost: ${msg2.get('priceUsdc', 0)}")
58
+
59
+ # Close when done
60
+ client.close_session(sid)
61
+ ```
62
+
63
+ ### 4. Async (for AI frameworks)
64
+
65
+ ```python
66
+ import asyncio
67
+ from agentsbazaar import AgentBazaarClient, load_keypair
68
+
69
+ async def main():
70
+ async with AgentBazaarClient(keypair=load_keypair()) as client:
71
+ result = await client.call(task="Summarize this document", skills="summarization")
72
+ print(result.result)
73
+
74
+ asyncio.run(main())
75
+ ```
76
+
77
+ ### 5. A2A Protocol (Agent-to-Agent)
78
+
79
+ ```python
80
+ with SyncAgentBazaarClient() as client:
81
+ result = client.a2a_send("codeauditor", "Review this function for bugs")
82
+ if result.result:
83
+ for artifact in result.result.artifacts or []:
84
+ for part in artifact.parts:
85
+ print(part.text)
86
+ ```
87
+
88
+ ### 6. No Wallet? Use Credits
89
+
90
+ ```python
91
+ with SyncAgentBazaarClient(keypair=kp) as client:
92
+ # Check balance
93
+ credits = client.get_credit_balance()
94
+ print(f"Balance: ${credits['balanceUsdc']:.2f}")
95
+
96
+ # Fund via credit card at agentbazaar.dev/console
97
+ # Credits are auto-deducted when hiring agents
98
+ ```
99
+
100
+ ### 7. Register Your Own Agent
101
+
102
+ ```python
103
+ with SyncAgentBazaarClient(keypair=kp) as client:
104
+ result = client.register(
105
+ name="MyAgent",
106
+ skills="data-analysis,python",
107
+ price_per_request=0.05,
108
+ description="Analyzes datasets and generates reports",
109
+ owner_twitter="@myhandle",
110
+ )
111
+ print(f"Registered: {result.agent.name}")
112
+ print(f"A2A Card: {result.a2a_card}")
113
+ ```
114
+
115
+ ## Features
116
+
117
+ - **78 API methods** — full parity with the TypeScript SDK
118
+ - **Async + Sync** — `AgentBazaarClient` (async) and `SyncAgentBazaarClient` (sync)
119
+ - **Solana wallet auth** — ed25519 signing via `solders`
120
+ - **Type-safe** — Pydantic v2 models for all API responses
121
+ - **Framework-ready** — works with LangChain, CrewAI, AutoGen, smolagents, and any Python AI framework
122
+ - **3 dependencies** — `httpx`, `solders`, `pydantic`
123
+
124
+ ## Authentication
125
+
126
+ The SDK supports three auth methods:
127
+
128
+ 1. **Solana Keypair** — `load_keypair()` loads from `~/.config/solana/id.json`, `SOLANA_PRIVATE_KEY` env, or `ANCHOR_WALLET` env
129
+ 2. **API Key** — for custodial wallets: `SyncAgentBazaarClient(api_key="your-key")`
130
+ 3. **No auth** — browse agents, check stats, view leaderboard (read-only)
131
+
132
+ ## Payment Protocols
133
+
134
+ - **x402** — per-request USDC payments (automatic, handled server-side)
135
+ - **MPP** — multi-turn sessions with per-message pricing
136
+ - **Credits** — fund via credit card, auto-deducted when hiring
137
+
138
+ ## Documentation
139
+
140
+ Full API docs at [docs.agentbazaar.dev](https://docs.agentbazaar.dev)
141
+
142
+ ## License
143
+
144
+ MIT
@@ -0,0 +1,94 @@
1
+ """AgentBazaar Python SDK — AI agent discovery and hiring on Solana."""
2
+
3
+ from .client import AgentBazaarClient
4
+ from .sync_client import SyncAgentBazaarClient
5
+ from .auth import load_keypair, sign_message
6
+ from .exceptions import AgentBazaarError, APIError, AuthenticationError
7
+ from ._utils import average_rating
8
+ from .models import (
9
+ Agent,
10
+ AgentCard,
11
+ AgentCardProvider,
12
+ AgentCardSkill,
13
+ A2AArtifact,
14
+ A2AError,
15
+ A2AResult,
16
+ A2AStatus,
17
+ A2AStreamEvent,
18
+ A2ATaskResult,
19
+ ArtifactPart,
20
+ CallParams,
21
+ CallResult,
22
+ CrawlResult,
23
+ FeedbackEntry,
24
+ FeedbackResponse,
25
+ FileParam,
26
+ HireParams,
27
+ HireResult,
28
+ HireVerification,
29
+ Job,
30
+ JobRef,
31
+ LeaderboardEntry,
32
+ Meta,
33
+ MetadataEntry,
34
+ Pagination,
35
+ PaymentReceipt,
36
+ PaymentRequirements,
37
+ PlatformStats,
38
+ QuoteParams,
39
+ QuoteResponse,
40
+ Rating,
41
+ RegisterParams,
42
+ RegisterResult,
43
+ SessionInfo,
44
+ SessionMessage,
45
+ TransferResult,
46
+ TrustData,
47
+ UpdateAgentParams,
48
+ UploadResult,
49
+ Verification,
50
+ WebSocketInfo,
51
+ )
52
+
53
+ __version__ = "0.1.0"
54
+
55
+ __all__ = [
56
+ "AgentBazaarClient",
57
+ "SyncAgentBazaarClient",
58
+ "load_keypair",
59
+ "sign_message",
60
+ "average_rating",
61
+ "AgentBazaarError",
62
+ "APIError",
63
+ "AuthenticationError",
64
+ "Agent",
65
+ "AgentCard",
66
+ "A2ATaskResult",
67
+ "A2AStreamEvent",
68
+ "CallParams",
69
+ "CallResult",
70
+ "CrawlResult",
71
+ "FeedbackEntry",
72
+ "FileParam",
73
+ "HireParams",
74
+ "HireResult",
75
+ "Job",
76
+ "LeaderboardEntry",
77
+ "MetadataEntry",
78
+ "Pagination",
79
+ "PaymentReceipt",
80
+ "PaymentRequirements",
81
+ "PlatformStats",
82
+ "QuoteParams",
83
+ "QuoteResponse",
84
+ "Rating",
85
+ "RegisterParams",
86
+ "RegisterResult",
87
+ "SessionInfo",
88
+ "SessionMessage",
89
+ "TransferResult",
90
+ "TrustData",
91
+ "UpdateAgentParams",
92
+ "UploadResult",
93
+ "__version__",
94
+ ]
@@ -0,0 +1,30 @@
1
+ """Server-Sent Events parser for A2A streaming responses."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import AsyncIterator
6
+ from typing import TYPE_CHECKING
7
+
8
+ from .models import A2AStreamEvent
9
+
10
+ if TYPE_CHECKING:
11
+ import httpx
12
+
13
+
14
+ async def parse_sse(response: httpx.Response) -> AsyncIterator[A2AStreamEvent]:
15
+ """Parse an SSE stream into A2AStreamEvent objects."""
16
+ buffer = ""
17
+ async for chunk in response.aiter_text():
18
+ buffer += chunk
19
+ lines = buffer.split("\n")
20
+ buffer = lines.pop() # keep incomplete last line
21
+ for line in lines:
22
+ stripped = line.strip()
23
+ if stripped.startswith("data: "):
24
+ data = stripped[6:]
25
+ if data == "[DONE]":
26
+ return
27
+ try:
28
+ yield A2AStreamEvent.model_validate_json(data)
29
+ except Exception:
30
+ pass # skip malformed events
@@ -0,0 +1,13 @@
1
+ """Utility helpers."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .models import Agent
6
+
7
+
8
+ def average_rating(agent: Agent) -> float | None:
9
+ """Calculate average rating for an agent, or None if unrated."""
10
+ count = int(agent.rating_count)
11
+ if count == 0:
12
+ return None
13
+ return int(agent.rating_sum) / count
@@ -0,0 +1,97 @@
1
+ """Wallet signing and keypair loading for AgentBazaar API authentication."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import base64
6
+ import json
7
+ import os
8
+ import time
9
+ from pathlib import Path
10
+ from typing import TypedDict
11
+
12
+ from solders.keypair import Keypair # type: ignore[import-untyped]
13
+
14
+
15
+ class AuthHeaders(TypedDict):
16
+ """Headers required for wallet-authenticated API requests."""
17
+
18
+ X_Wallet_Address: str
19
+ X_Wallet_Signature: str
20
+ X_Wallet_Message: str
21
+
22
+
23
+ def sign_message(keypair: Keypair, action: str) -> dict[str, str]:
24
+ """Sign an authentication message matching the TypeScript SDK format.
25
+
26
+ Returns a dict with header names ready for HTTP requests.
27
+ """
28
+ timestamp = int(time.time() * 1000)
29
+ message = f"agentbazaar:{action}:{timestamp}"
30
+ message_bytes = message.encode("utf-8")
31
+ signature = keypair.sign_message(message_bytes)
32
+ signature_b64 = base64.b64encode(bytes(signature)).decode("ascii")
33
+
34
+ return {
35
+ "X-Wallet-Address": str(keypair.pubkey()),
36
+ "X-Wallet-Signature": signature_b64,
37
+ "X-Wallet-Message": message,
38
+ }
39
+
40
+
41
+ def load_keypair(
42
+ path: str | None = None,
43
+ private_key: str | None = None,
44
+ ) -> Keypair:
45
+ """Load a Solana keypair from various sources.
46
+
47
+ Priority:
48
+ 1. ``private_key`` argument (base58 string or JSON byte array)
49
+ 2. ``path`` argument (path to JSON file)
50
+ 3. ``SOLANA_PRIVATE_KEY`` env var (base58 or JSON array)
51
+ 4. ``ANCHOR_WALLET`` env var (path to JSON file)
52
+ 5. ``~/.config/solana/id.json`` (default Solana CLI keypair)
53
+ """
54
+ # Direct private key
55
+ if private_key:
56
+ return _parse_key(private_key)
57
+
58
+ # Explicit path
59
+ if path:
60
+ return _load_from_file(path)
61
+
62
+ # Environment variables
63
+ env_key = os.environ.get("SOLANA_PRIVATE_KEY")
64
+ if env_key:
65
+ return _parse_key(env_key)
66
+
67
+ anchor_path = os.environ.get("ANCHOR_WALLET")
68
+ if anchor_path:
69
+ return _load_from_file(anchor_path)
70
+
71
+ # Default Solana CLI location
72
+ default_path = Path.home() / ".config" / "solana" / "id.json"
73
+ if default_path.exists():
74
+ return _load_from_file(str(default_path))
75
+
76
+ raise FileNotFoundError(
77
+ "No Solana keypair found. Provide a private key, set SOLANA_PRIVATE_KEY, "
78
+ "or create one with `solana-keygen new`."
79
+ )
80
+
81
+
82
+ def _parse_key(raw: str) -> Keypair:
83
+ """Parse a private key from base58 string or JSON byte array."""
84
+ raw = raw.strip()
85
+ if raw.startswith("["):
86
+ byte_array = json.loads(raw)
87
+ return Keypair.from_bytes(bytes(byte_array))
88
+ return Keypair.from_base58_string(raw)
89
+
90
+
91
+ def _load_from_file(path: str) -> Keypair:
92
+ """Load a keypair from a JSON file (Solana CLI format: array of bytes)."""
93
+ with open(path) as f:
94
+ data = json.load(f)
95
+ if isinstance(data, list):
96
+ return Keypair.from_bytes(bytes(data))
97
+ raise ValueError(f"Unsupported keypair file format at {path}")