agent0-sdk 1.4.2__py3-none-any.whl → 1.5.1b1__py3-none-any.whl
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.
- agent0_sdk/__init__.py +7 -3
- agent0_sdk/core/contracts.py +1 -0
- agent0_sdk/core/feedback_manager.py +75 -78
- agent0_sdk/core/indexer.py +645 -635
- agent0_sdk/core/models.py +91 -12
- agent0_sdk/core/sdk.py +26 -314
- agent0_sdk/core/semantic_search_client.py +70 -0
- agent0_sdk/core/subgraph_client.py +182 -239
- {agent0_sdk-1.4.2.dist-info → agent0_sdk-1.5.1b1.dist-info}/METADATA +163 -9
- agent0_sdk-1.5.1b1.dist-info/RECORD +22 -0
- agent0_sdk-1.4.2.dist-info/RECORD +0 -21
- {agent0_sdk-1.4.2.dist-info → agent0_sdk-1.5.1b1.dist-info}/WHEEL +0 -0
- {agent0_sdk-1.4.2.dist-info → agent0_sdk-1.5.1b1.dist-info}/licenses/LICENSE +0 -0
- {agent0_sdk-1.4.2.dist-info → agent0_sdk-1.5.1b1.dist-info}/top_level.txt +0 -0
|
@@ -67,6 +67,12 @@ class SubgraphClient:
|
|
|
67
67
|
logger.debug("Subgraph schema missing agentWallet fields; retrying query without them")
|
|
68
68
|
q2 = query.replace("agentWalletChainId", "").replace("agentWallet", "")
|
|
69
69
|
return _do_query(q2)
|
|
70
|
+
# Some deployments do not yet expose `hasOASF` on AgentRegistrationFile.
|
|
71
|
+
if (("has no field" in msg and "hasOASF" in msg) or ("Cannot query field" in msg and "hasOASF" in msg)) and (
|
|
72
|
+
"hasOASF" in query
|
|
73
|
+
):
|
|
74
|
+
logger.debug("Subgraph schema missing hasOASF; retrying query without it")
|
|
75
|
+
return _do_query(query.replace("hasOASF", "oasfEndpoint"))
|
|
70
76
|
raise
|
|
71
77
|
except requests.exceptions.RequestException as e:
|
|
72
78
|
raise ConnectionError(f"Failed to query subgraph: {e}")
|
|
@@ -167,6 +173,181 @@ class SubgraphClient:
|
|
|
167
173
|
result = self.query(query)
|
|
168
174
|
return result.get('agents', [])
|
|
169
175
|
|
|
176
|
+
# -------------------------------------------------------------------------
|
|
177
|
+
# V2 query helpers (variable-based where clauses; used by unified search)
|
|
178
|
+
# -------------------------------------------------------------------------
|
|
179
|
+
|
|
180
|
+
def get_agents_v2(
|
|
181
|
+
self,
|
|
182
|
+
where: Optional[Dict[str, Any]],
|
|
183
|
+
first: int,
|
|
184
|
+
skip: int,
|
|
185
|
+
order_by: str,
|
|
186
|
+
order_direction: str,
|
|
187
|
+
) -> List[Dict[str, Any]]:
|
|
188
|
+
query = """
|
|
189
|
+
query SearchAgentsV2($where: Agent_filter, $first: Int!, $skip: Int!, $orderBy: Agent_orderBy!, $orderDirection: OrderDirection!) {
|
|
190
|
+
agents(where: $where, first: $first, skip: $skip, orderBy: $orderBy, orderDirection: $orderDirection) {
|
|
191
|
+
id
|
|
192
|
+
chainId
|
|
193
|
+
agentId
|
|
194
|
+
agentURI
|
|
195
|
+
agentURIType
|
|
196
|
+
owner
|
|
197
|
+
operators
|
|
198
|
+
agentWallet
|
|
199
|
+
totalFeedback
|
|
200
|
+
createdAt
|
|
201
|
+
updatedAt
|
|
202
|
+
lastActivity
|
|
203
|
+
registrationFile {
|
|
204
|
+
id
|
|
205
|
+
agentId
|
|
206
|
+
name
|
|
207
|
+
description
|
|
208
|
+
image
|
|
209
|
+
active
|
|
210
|
+
x402Support
|
|
211
|
+
supportedTrusts
|
|
212
|
+
mcpEndpoint
|
|
213
|
+
mcpVersion
|
|
214
|
+
a2aEndpoint
|
|
215
|
+
a2aVersion
|
|
216
|
+
webEndpoint
|
|
217
|
+
emailEndpoint
|
|
218
|
+
hasOASF
|
|
219
|
+
oasfSkills
|
|
220
|
+
oasfDomains
|
|
221
|
+
ens
|
|
222
|
+
did
|
|
223
|
+
mcpTools
|
|
224
|
+
mcpPrompts
|
|
225
|
+
mcpResources
|
|
226
|
+
a2aSkills
|
|
227
|
+
createdAt
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
"""
|
|
232
|
+
variables = {
|
|
233
|
+
"where": where,
|
|
234
|
+
"first": first,
|
|
235
|
+
"skip": skip,
|
|
236
|
+
"orderBy": order_by,
|
|
237
|
+
"orderDirection": order_direction,
|
|
238
|
+
}
|
|
239
|
+
try:
|
|
240
|
+
data = self.query(query, variables)
|
|
241
|
+
return data.get("agents", [])
|
|
242
|
+
except ValueError as e:
|
|
243
|
+
# Compatibility: some deployments do not support AgentRegistrationFile.hasOASF in the *filter input*.
|
|
244
|
+
# Retry by translating registrationFile_.hasOASF => oasfEndpoint existence checks.
|
|
245
|
+
msg = str(e)
|
|
246
|
+
if where and "hasOASF" in msg and ("AgentRegistrationFile" in msg or "AgentRegistrationFile_filter" in msg):
|
|
247
|
+
def rewrite(node: Any) -> Any:
|
|
248
|
+
if isinstance(node, list):
|
|
249
|
+
return [rewrite(x) for x in node]
|
|
250
|
+
if not isinstance(node, dict):
|
|
251
|
+
return node
|
|
252
|
+
out: Dict[str, Any] = {}
|
|
253
|
+
for k, v in node.items():
|
|
254
|
+
if k == "registrationFile_" and isinstance(v, dict):
|
|
255
|
+
rf = dict(v)
|
|
256
|
+
if "hasOASF" in rf:
|
|
257
|
+
want = bool(rf.get("hasOASF"))
|
|
258
|
+
rf.pop("hasOASF", None)
|
|
259
|
+
if want:
|
|
260
|
+
rf["oasfEndpoint_not"] = None
|
|
261
|
+
else:
|
|
262
|
+
rf["oasfEndpoint"] = None
|
|
263
|
+
out[k] = rewrite(rf)
|
|
264
|
+
else:
|
|
265
|
+
out[k] = rewrite(v)
|
|
266
|
+
return out
|
|
267
|
+
|
|
268
|
+
variables2 = dict(variables)
|
|
269
|
+
variables2["where"] = rewrite(where)
|
|
270
|
+
data2 = self.query(query, variables2)
|
|
271
|
+
return data2.get("agents", [])
|
|
272
|
+
raise
|
|
273
|
+
|
|
274
|
+
def query_agent_metadatas(self, where: Dict[str, Any], first: int, skip: int) -> List[Dict[str, Any]]:
|
|
275
|
+
query = """
|
|
276
|
+
query AgentMetadatas($where: AgentMetadata_filter, $first: Int!, $skip: Int!) {
|
|
277
|
+
agentMetadatas(where: $where, first: $first, skip: $skip) {
|
|
278
|
+
id
|
|
279
|
+
key
|
|
280
|
+
value
|
|
281
|
+
updatedAt
|
|
282
|
+
agent { id }
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
"""
|
|
286
|
+
try:
|
|
287
|
+
data = self.query(query, {"where": where, "first": first, "skip": skip})
|
|
288
|
+
return data.get("agentMetadatas", [])
|
|
289
|
+
except ValueError as e:
|
|
290
|
+
# Hosted subgraph compatibility: some deployments expose AgentMetadata list as `agentMetadata_collection`.
|
|
291
|
+
msg = str(e)
|
|
292
|
+
if ("has no field" in msg and "agentMetadatas" in msg) or ("Cannot query field" in msg and "agentMetadatas" in msg):
|
|
293
|
+
query2 = """
|
|
294
|
+
query AgentMetadataCollection($where: AgentMetadata_filter, $first: Int!, $skip: Int!) {
|
|
295
|
+
agentMetadata_collection(where: $where, first: $first, skip: $skip) {
|
|
296
|
+
id
|
|
297
|
+
key
|
|
298
|
+
value
|
|
299
|
+
updatedAt
|
|
300
|
+
agent { id }
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
"""
|
|
304
|
+
data2 = self.query(query2, {"where": where, "first": first, "skip": skip})
|
|
305
|
+
return data2.get("agentMetadata_collection", [])
|
|
306
|
+
raise
|
|
307
|
+
|
|
308
|
+
def query_feedbacks_minimal(
|
|
309
|
+
self,
|
|
310
|
+
where: Dict[str, Any],
|
|
311
|
+
first: int,
|
|
312
|
+
skip: int,
|
|
313
|
+
order_by: str = "createdAt",
|
|
314
|
+
order_direction: str = "desc",
|
|
315
|
+
) -> List[Dict[str, Any]]:
|
|
316
|
+
query = """
|
|
317
|
+
query Feedbacks($where: Feedback_filter, $first: Int!, $skip: Int!, $orderBy: Feedback_orderBy!, $orderDirection: OrderDirection!) {
|
|
318
|
+
feedbacks(where: $where, first: $first, skip: $skip, orderBy: $orderBy, orderDirection: $orderDirection) {
|
|
319
|
+
id
|
|
320
|
+
agent { id }
|
|
321
|
+
clientAddress
|
|
322
|
+
value
|
|
323
|
+
tag1
|
|
324
|
+
tag2
|
|
325
|
+
endpoint
|
|
326
|
+
isRevoked
|
|
327
|
+
createdAt
|
|
328
|
+
responses(first: 1) { id }
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
"""
|
|
332
|
+
data = self.query(
|
|
333
|
+
query,
|
|
334
|
+
{"where": where, "first": first, "skip": skip, "orderBy": order_by, "orderDirection": order_direction},
|
|
335
|
+
)
|
|
336
|
+
return data.get("feedbacks", [])
|
|
337
|
+
|
|
338
|
+
def query_feedback_responses(self, where: Dict[str, Any], first: int, skip: int) -> List[Dict[str, Any]]:
|
|
339
|
+
query = """
|
|
340
|
+
query FeedbackResponses($where: FeedbackResponse_filter, $first: Int!, $skip: Int!) {
|
|
341
|
+
feedbackResponses(where: $where, first: $first, skip: $skip) {
|
|
342
|
+
id
|
|
343
|
+
feedback { id }
|
|
344
|
+
createdAt
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
"""
|
|
348
|
+
data = self.query(query, {"where": where, "first": first, "skip": skip})
|
|
349
|
+
return data.get("feedbackResponses", [])
|
|
350
|
+
|
|
170
351
|
def get_agent_by_id(self, agent_id: str, include_registration_file: bool = True) -> Optional[Dict[str, Any]]:
|
|
171
352
|
"""
|
|
172
353
|
Get a specific agent by ID.
|
|
@@ -612,242 +793,4 @@ class SubgraphClient:
|
|
|
612
793
|
result = self.query(query)
|
|
613
794
|
return result.get('feedbacks', [])
|
|
614
795
|
|
|
615
|
-
|
|
616
|
-
self,
|
|
617
|
-
agents: Optional[List[str]] = None,
|
|
618
|
-
tags: Optional[List[str]] = None,
|
|
619
|
-
reviewers: Optional[List[str]] = None,
|
|
620
|
-
capabilities: Optional[List[str]] = None,
|
|
621
|
-
skills: Optional[List[str]] = None,
|
|
622
|
-
tasks: Optional[List[str]] = None,
|
|
623
|
-
names: Optional[List[str]] = None,
|
|
624
|
-
minAverageValue: Optional[float] = None,
|
|
625
|
-
includeRevoked: bool = False,
|
|
626
|
-
first: int = 100,
|
|
627
|
-
skip: int = 0,
|
|
628
|
-
order_by: str = "createdAt",
|
|
629
|
-
order_direction: str = "desc",
|
|
630
|
-
) -> List[Dict[str, Any]]:
|
|
631
|
-
"""
|
|
632
|
-
Search agents filtered by reputation criteria.
|
|
633
|
-
|
|
634
|
-
Args:
|
|
635
|
-
agents: List of agent IDs to filter by
|
|
636
|
-
tags: List of tags to filter feedback by
|
|
637
|
-
reviewers: List of reviewer addresses to filter feedback by
|
|
638
|
-
capabilities: List of capabilities to filter feedback by
|
|
639
|
-
skills: List of skills to filter feedback by
|
|
640
|
-
tasks: List of tasks to filter feedback by
|
|
641
|
-
minAverageValue: Minimum average value for included agents
|
|
642
|
-
includeRevoked: Whether to include revoked feedback in calculations
|
|
643
|
-
first: Number of results to return
|
|
644
|
-
skip: Number of results to skip
|
|
645
|
-
order_by: Field to order by
|
|
646
|
-
order_direction: Sort direction (asc/desc)
|
|
647
|
-
|
|
648
|
-
Returns:
|
|
649
|
-
List of agents with averageValue field calculated from filtered feedback
|
|
650
|
-
"""
|
|
651
|
-
# Build feedback filter
|
|
652
|
-
feedback_filters = []
|
|
653
|
-
|
|
654
|
-
if not includeRevoked:
|
|
655
|
-
feedback_filters.append('isRevoked: false')
|
|
656
|
-
|
|
657
|
-
if tags is not None and len(tags) > 0:
|
|
658
|
-
# Tags are now stored as human-readable strings in the subgraph
|
|
659
|
-
tag_filter = []
|
|
660
|
-
for tag in tags:
|
|
661
|
-
tag_filter.append(f'{{or: [{{tag1: "{tag}"}}, {{tag2: "{tag}"}}]}}')
|
|
662
|
-
feedback_filters.append(f'or: [{", ".join(tag_filter)}]')
|
|
663
|
-
|
|
664
|
-
if reviewers is not None and len(reviewers) > 0:
|
|
665
|
-
reviewers_list = [f'"{addr}"' for addr in reviewers]
|
|
666
|
-
feedback_filters.append(f'clientAddress_in: [{", ".join(reviewers_list)}]')
|
|
667
|
-
|
|
668
|
-
# Feedback file filters
|
|
669
|
-
feedback_file_filters = []
|
|
670
|
-
|
|
671
|
-
if capabilities is not None and len(capabilities) > 0:
|
|
672
|
-
capabilities_list = [f'"{cap}"' for cap in capabilities]
|
|
673
|
-
feedback_file_filters.append(f'capability_in: [{", ".join(capabilities_list)}]')
|
|
674
|
-
|
|
675
|
-
if skills is not None and len(skills) > 0:
|
|
676
|
-
skills_list = [f'"{skill}"' for skill in skills]
|
|
677
|
-
feedback_file_filters.append(f'skill_in: [{", ".join(skills_list)}]')
|
|
678
|
-
|
|
679
|
-
if tasks is not None and len(tasks) > 0:
|
|
680
|
-
tasks_list = [f'"{task}"' for task in tasks]
|
|
681
|
-
feedback_file_filters.append(f'task_in: [{", ".join(tasks_list)}]')
|
|
682
|
-
|
|
683
|
-
if names is not None and len(names) > 0:
|
|
684
|
-
names_list = [f'"{name}"' for name in names]
|
|
685
|
-
feedback_file_filters.append(f'name_in: [{", ".join(names_list)}]')
|
|
686
|
-
|
|
687
|
-
if feedback_file_filters:
|
|
688
|
-
feedback_filters.append(f'feedbackFile_: {{ {", ".join(feedback_file_filters)} }}')
|
|
689
|
-
|
|
690
|
-
# If we have feedback filters (tags, capabilities, skills, etc.), we need to first
|
|
691
|
-
# query feedback to get agent IDs, then query those agents
|
|
692
|
-
# Otherwise, query agents directly
|
|
693
|
-
if tags or capabilities or skills or tasks or names or reviewers:
|
|
694
|
-
# First, query feedback to get unique agent IDs that have matching feedback
|
|
695
|
-
feedback_where = f"{{ {', '.join(feedback_filters)} }}" if feedback_filters else "{}"
|
|
696
|
-
|
|
697
|
-
feedback_query = f"""
|
|
698
|
-
{{
|
|
699
|
-
feedbacks(
|
|
700
|
-
where: {feedback_where}
|
|
701
|
-
first: 1000
|
|
702
|
-
skip: 0
|
|
703
|
-
) {{
|
|
704
|
-
agent {{
|
|
705
|
-
id
|
|
706
|
-
}}
|
|
707
|
-
}}
|
|
708
|
-
}}
|
|
709
|
-
"""
|
|
710
|
-
|
|
711
|
-
try:
|
|
712
|
-
feedback_result = self.query(feedback_query)
|
|
713
|
-
feedbacks_data = feedback_result.get('feedbacks', [])
|
|
714
|
-
|
|
715
|
-
# Extract unique agent IDs
|
|
716
|
-
agent_ids_set = set()
|
|
717
|
-
for fb in feedbacks_data:
|
|
718
|
-
agent = fb.get('agent', {})
|
|
719
|
-
agent_id = agent.get('id')
|
|
720
|
-
if agent_id:
|
|
721
|
-
agent_ids_set.add(agent_id)
|
|
722
|
-
|
|
723
|
-
if not agent_ids_set:
|
|
724
|
-
# No agents have matching feedback
|
|
725
|
-
return []
|
|
726
|
-
|
|
727
|
-
# Now query only those agents
|
|
728
|
-
agent_ids_list = list(agent_ids_set)
|
|
729
|
-
# Apply any agent filters if specified
|
|
730
|
-
if agents is not None and len(agents) > 0:
|
|
731
|
-
agent_ids_list = [aid for aid in agent_ids_list if aid in agents]
|
|
732
|
-
if not agent_ids_list:
|
|
733
|
-
return []
|
|
734
|
-
|
|
735
|
-
# Query agents (limit to first N based on pagination)
|
|
736
|
-
agent_ids_str = ', '.join([f'"{aid}"' for aid in agent_ids_list])
|
|
737
|
-
agent_where = f"where: {{ id_in: [{agent_ids_str}] }}"
|
|
738
|
-
except Exception as e:
|
|
739
|
-
logger.warning(f"Failed to query feedback for agent IDs: {e}")
|
|
740
|
-
return []
|
|
741
|
-
else:
|
|
742
|
-
# No feedback filters - query agents directly
|
|
743
|
-
# For reputation search, we want agents that have feedback
|
|
744
|
-
# Filter by totalFeedback > 0 to only get agents with feedback
|
|
745
|
-
agent_filters = ['totalFeedback_gt: 0'] # Only agents with feedback (BigInt comparison)
|
|
746
|
-
if agents is not None and len(agents) > 0:
|
|
747
|
-
agent_ids = [f'"{aid}"' for aid in agents]
|
|
748
|
-
agent_filters.append(f'id_in: [{", ".join(agent_ids)}]')
|
|
749
|
-
|
|
750
|
-
agent_where = f"where: {{ {', '.join(agent_filters)} }}"
|
|
751
|
-
|
|
752
|
-
# Build feedback where for agent query (to calculate scores)
|
|
753
|
-
feedback_where_for_agents = f"{{ {', '.join(feedback_filters)} }}" if feedback_filters else "{}"
|
|
754
|
-
|
|
755
|
-
query = f"""
|
|
756
|
-
{{
|
|
757
|
-
agents(
|
|
758
|
-
{agent_where}
|
|
759
|
-
first: {first}
|
|
760
|
-
skip: {skip}
|
|
761
|
-
orderBy: {order_by}
|
|
762
|
-
orderDirection: {order_direction}
|
|
763
|
-
) {{
|
|
764
|
-
id
|
|
765
|
-
chainId
|
|
766
|
-
agentId
|
|
767
|
-
agentURI
|
|
768
|
-
agentURIType
|
|
769
|
-
owner
|
|
770
|
-
operators
|
|
771
|
-
createdAt
|
|
772
|
-
updatedAt
|
|
773
|
-
totalFeedback
|
|
774
|
-
lastActivity
|
|
775
|
-
registrationFile {{
|
|
776
|
-
id
|
|
777
|
-
name
|
|
778
|
-
description
|
|
779
|
-
image
|
|
780
|
-
active
|
|
781
|
-
x402Support
|
|
782
|
-
supportedTrusts
|
|
783
|
-
mcpEndpoint
|
|
784
|
-
mcpVersion
|
|
785
|
-
a2aEndpoint
|
|
786
|
-
a2aVersion
|
|
787
|
-
ens
|
|
788
|
-
did
|
|
789
|
-
agentWallet
|
|
790
|
-
agentWalletChainId
|
|
791
|
-
mcpTools
|
|
792
|
-
mcpPrompts
|
|
793
|
-
mcpResources
|
|
794
|
-
a2aSkills
|
|
795
|
-
createdAt
|
|
796
|
-
}}
|
|
797
|
-
feedback(where: {feedback_where_for_agents}) {{
|
|
798
|
-
value
|
|
799
|
-
isRevoked
|
|
800
|
-
feedbackFile {{
|
|
801
|
-
capability
|
|
802
|
-
skill
|
|
803
|
-
task
|
|
804
|
-
name
|
|
805
|
-
}}
|
|
806
|
-
}}
|
|
807
|
-
}}
|
|
808
|
-
}}
|
|
809
|
-
"""
|
|
810
|
-
|
|
811
|
-
try:
|
|
812
|
-
result = self.query(query)
|
|
813
|
-
|
|
814
|
-
# Check for GraphQL errors
|
|
815
|
-
if 'errors' in result:
|
|
816
|
-
logger.error(f"GraphQL errors in search_agents_by_reputation: {result['errors']}")
|
|
817
|
-
return []
|
|
818
|
-
|
|
819
|
-
agents_result = result.get('agents', [])
|
|
820
|
-
|
|
821
|
-
# Calculate average values
|
|
822
|
-
for agent in agents_result:
|
|
823
|
-
feedbacks = agent.get('feedback', [])
|
|
824
|
-
if feedbacks:
|
|
825
|
-
values = [float(fb["value"]) for fb in feedbacks if fb.get("value") is not None]
|
|
826
|
-
agent["averageValue"] = (sum(values) / len(values)) if values else None
|
|
827
|
-
else:
|
|
828
|
-
agent["averageValue"] = None
|
|
829
|
-
|
|
830
|
-
# Filter by minAverageValue
|
|
831
|
-
if minAverageValue is not None:
|
|
832
|
-
agents_result = [
|
|
833
|
-
agent for agent in agents_result
|
|
834
|
-
if agent.get("averageValue") is not None and agent["averageValue"] >= minAverageValue
|
|
835
|
-
]
|
|
836
|
-
|
|
837
|
-
# For reputation search, filter logic:
|
|
838
|
-
# - If specific agents were requested, return them even if averageValue is None
|
|
839
|
-
# (the user explicitly asked for these agents, so return them)
|
|
840
|
-
# - If general search (no specific agents), only return agents with reputation data
|
|
841
|
-
if agents is None or len(agents) == 0:
|
|
842
|
-
# General search - only return agents with reputation
|
|
843
|
-
agents_result = [
|
|
844
|
-
agent for agent in agents_result
|
|
845
|
-
if agent.get("averageValue") is not None
|
|
846
|
-
]
|
|
847
|
-
# else: specific agents requested - return all requested agents (even if averageValue is None)
|
|
848
|
-
|
|
849
|
-
return agents_result
|
|
850
|
-
|
|
851
|
-
except Exception as e:
|
|
852
|
-
logger.warning(f"Subgraph reputation search failed: {e}")
|
|
853
|
-
return []
|
|
796
|
+
# NOTE: `search_agents_by_reputation` was removed in favor of unified `SDK.searchAgents()` with `filters.feedback`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent0-sdk
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.1b1
|
|
4
4
|
Summary: Python SDK for agent portability, discovery and trust based on ERC-8004
|
|
5
5
|
Author-email: Agent0 Team <team@ag0.xyz>
|
|
6
6
|
License: MIT License
|
|
@@ -104,6 +104,12 @@ Agent0 SDK enables you to:
|
|
|
104
104
|
pip install agent0-sdk
|
|
105
105
|
```
|
|
106
106
|
|
|
107
|
+
To install the **1.5.1 pre-release** explicitly:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
pip install --pre agent0-sdk==1.5.1b1
|
|
111
|
+
```
|
|
112
|
+
|
|
107
113
|
### Install from Source
|
|
108
114
|
|
|
109
115
|
```bash
|
|
@@ -198,14 +204,18 @@ print(f"Updated: {update.agentURI}")
|
|
|
198
204
|
```python
|
|
199
205
|
# Search by name, capabilities, or attributes
|
|
200
206
|
results = sdk.searchAgents(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
207
|
+
filters={
|
|
208
|
+
"name": "AI", # substring
|
|
209
|
+
"mcpTools": ["code_generation"],
|
|
210
|
+
"a2aSkills": ["python"],
|
|
211
|
+
"active": True,
|
|
212
|
+
"x402support": True,
|
|
213
|
+
"feedback": {"minValue": 80, "tag": "enterprise", "includeRevoked": False},
|
|
214
|
+
},
|
|
215
|
+
options={"sort": ["updatedAt:desc"]},
|
|
206
216
|
)
|
|
207
217
|
|
|
208
|
-
for agent in results
|
|
218
|
+
for agent in results:
|
|
209
219
|
print(f"{agent.name}: {agent.description}")
|
|
210
220
|
print(f" Tools: {agent.mcpTools}")
|
|
211
221
|
print(f" Skills: {agent.a2aSkills}")
|
|
@@ -355,6 +365,151 @@ The SDK includes complete OASF v0.8.0 taxonomy files:
|
|
|
355
365
|
|
|
356
366
|
Browse these files to find appropriate skill and domain slugs. For more information, see the [OASF specification](https://github.com/agntcy/oasf) and [Release Notes v0.31](RELEASE_NOTES_0.31.md).
|
|
357
367
|
|
|
368
|
+
## Unified Search Reference (Exhaustive)
|
|
369
|
+
|
|
370
|
+
The unified search API is:
|
|
371
|
+
|
|
372
|
+
```python
|
|
373
|
+
results = sdk.searchAgents(filters: dict | SearchFilters | None = None, options: dict | SearchOptions | None = None)
|
|
374
|
+
# results: list[AgentSummary]
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### `FeedbackFilters` (used as `filters["feedback"]`)
|
|
378
|
+
|
|
379
|
+
```python
|
|
380
|
+
@dataclass
|
|
381
|
+
class FeedbackFilters:
|
|
382
|
+
hasFeedback: Optional[bool] = None
|
|
383
|
+
hasNoFeedback: Optional[bool] = None
|
|
384
|
+
includeRevoked: Optional[bool] = None
|
|
385
|
+
minValue: Optional[float] = None
|
|
386
|
+
maxValue: Optional[float] = None
|
|
387
|
+
minCount: Optional[int] = None
|
|
388
|
+
maxCount: Optional[int] = None
|
|
389
|
+
fromReviewers: Optional[List[Address]] = None
|
|
390
|
+
endpoint: Optional[str] = None # substring match
|
|
391
|
+
hasResponse: Optional[bool] = None
|
|
392
|
+
tag1: Optional[str] = None
|
|
393
|
+
tag2: Optional[str] = None
|
|
394
|
+
tag: Optional[str] = None # matches tag1 OR tag2
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
| Field | Semantics |
|
|
398
|
+
| --- | --- |
|
|
399
|
+
| `hasFeedback` / `hasNoFeedback` | Filter by whether the agent has any feedback |
|
|
400
|
+
| `includeRevoked` | Include revoked feedback entries in the pool used for filtering |
|
|
401
|
+
| `minValue` / `maxValue` | Threshold on **average value** over feedback matching the other feedback constraints (inclusive) |
|
|
402
|
+
| `minCount` / `maxCount` | Threshold on **count** over feedback matching the other feedback constraints (inclusive) |
|
|
403
|
+
| `fromReviewers` | Only consider feedback from these reviewer wallets |
|
|
404
|
+
| `endpoint` | Only consider feedback whose `endpoint` contains this substring |
|
|
405
|
+
| `hasResponse` | Only consider feedback that has at least one response (if supported) |
|
|
406
|
+
| `tag1` / `tag2` | Only consider feedback matching tag1/tag2 |
|
|
407
|
+
| `tag` | Shorthand: match either tag1 OR tag2 |
|
|
408
|
+
|
|
409
|
+
### `SearchFilters`
|
|
410
|
+
|
|
411
|
+
```python
|
|
412
|
+
DateLike = Union[datetime, str, int]
|
|
413
|
+
|
|
414
|
+
@dataclass
|
|
415
|
+
class SearchFilters:
|
|
416
|
+
chains: Optional[Union[List[ChainId], Literal["all"]]] = None
|
|
417
|
+
agentIds: Optional[List[AgentId]] = None
|
|
418
|
+
|
|
419
|
+
name: Optional[str] = None
|
|
420
|
+
description: Optional[str] = None
|
|
421
|
+
|
|
422
|
+
owners: Optional[List[Address]] = None
|
|
423
|
+
operators: Optional[List[Address]] = None
|
|
424
|
+
|
|
425
|
+
hasRegistrationFile: Optional[bool] = None
|
|
426
|
+
hasWeb: Optional[bool] = None
|
|
427
|
+
hasMCP: Optional[bool] = None
|
|
428
|
+
hasA2A: Optional[bool] = None
|
|
429
|
+
hasOASF: Optional[bool] = None
|
|
430
|
+
hasEndpoints: Optional[bool] = None
|
|
431
|
+
|
|
432
|
+
webContains: Optional[str] = None
|
|
433
|
+
mcpContains: Optional[str] = None
|
|
434
|
+
a2aContains: Optional[str] = None
|
|
435
|
+
ensContains: Optional[str] = None
|
|
436
|
+
didContains: Optional[str] = None
|
|
437
|
+
|
|
438
|
+
walletAddress: Optional[Address] = None
|
|
439
|
+
|
|
440
|
+
supportedTrust: Optional[List[str]] = None
|
|
441
|
+
a2aSkills: Optional[List[str]] = None
|
|
442
|
+
mcpTools: Optional[List[str]] = None
|
|
443
|
+
mcpPrompts: Optional[List[str]] = None
|
|
444
|
+
mcpResources: Optional[List[str]] = None
|
|
445
|
+
oasfSkills: Optional[List[str]] = None
|
|
446
|
+
oasfDomains: Optional[List[str]] = None
|
|
447
|
+
|
|
448
|
+
active: Optional[bool] = None
|
|
449
|
+
x402support: Optional[bool] = None
|
|
450
|
+
|
|
451
|
+
registeredAtFrom: Optional[DateLike] = None
|
|
452
|
+
registeredAtTo: Optional[DateLike] = None
|
|
453
|
+
updatedAtFrom: Optional[DateLike] = None
|
|
454
|
+
updatedAtTo: Optional[DateLike] = None
|
|
455
|
+
|
|
456
|
+
hasMetadataKey: Optional[str] = None
|
|
457
|
+
metadataValue: Optional[Dict[str, str]] = None # { key, value }
|
|
458
|
+
|
|
459
|
+
keyword: Optional[str] = None
|
|
460
|
+
feedback: Optional[FeedbackFilters] = None
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
### `SearchOptions`
|
|
464
|
+
|
|
465
|
+
```python
|
|
466
|
+
@dataclass
|
|
467
|
+
class SearchOptions:
|
|
468
|
+
sort: Optional[List[str]] = None
|
|
469
|
+
semanticMinScore: Optional[float] = None
|
|
470
|
+
semanticTopK: Optional[int] = None
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
### `AgentSummary` (returned items)
|
|
474
|
+
|
|
475
|
+
```python
|
|
476
|
+
@dataclass
|
|
477
|
+
class AgentSummary:
|
|
478
|
+
chainId: ChainId
|
|
479
|
+
agentId: AgentId
|
|
480
|
+
name: str
|
|
481
|
+
image: Optional[URI]
|
|
482
|
+
description: str
|
|
483
|
+
owners: List[Address]
|
|
484
|
+
operators: List[Address]
|
|
485
|
+
# Endpoint strings (present when advertised; not booleans)
|
|
486
|
+
mcp: Optional[str] = None
|
|
487
|
+
a2a: Optional[str] = None
|
|
488
|
+
web: Optional[str] = None
|
|
489
|
+
email: Optional[str] = None
|
|
490
|
+
ens: Optional[str] = None
|
|
491
|
+
did: Optional[str] = None
|
|
492
|
+
walletAddress: Optional[Address] = None
|
|
493
|
+
supportedTrusts: List[str] = field(default_factory=list)
|
|
494
|
+
a2aSkills: List[str] = field(default_factory=list)
|
|
495
|
+
mcpTools: List[str] = field(default_factory=list)
|
|
496
|
+
mcpPrompts: List[str] = field(default_factory=list)
|
|
497
|
+
mcpResources: List[str] = field(default_factory=list)
|
|
498
|
+
oasfSkills: List[str] = field(default_factory=list)
|
|
499
|
+
oasfDomains: List[str] = field(default_factory=list)
|
|
500
|
+
active: bool = False
|
|
501
|
+
x402support: bool = False
|
|
502
|
+
createdAt: Optional[int] = None
|
|
503
|
+
updatedAt: Optional[int] = None
|
|
504
|
+
lastActivity: Optional[int] = None
|
|
505
|
+
agentURI: Optional[str] = None
|
|
506
|
+
agentURIType: Optional[str] = None
|
|
507
|
+
feedbackCount: Optional[int] = None
|
|
508
|
+
averageValue: Optional[float] = None
|
|
509
|
+
semanticScore: Optional[float] = None
|
|
510
|
+
extras: Dict[str, Any] = field(default_factory=dict)
|
|
511
|
+
```
|
|
512
|
+
|
|
358
513
|
## Use Cases
|
|
359
514
|
|
|
360
515
|
- **Building agent marketplaces** - Create platforms where developers can discover, evaluate, and integrate agents based on their capabilities and reputation
|
|
@@ -364,10 +519,9 @@ Browse these files to find appropriate skill and domain slugs. For more informat
|
|
|
364
519
|
|
|
365
520
|
## 🚀 Coming Soon
|
|
366
521
|
|
|
367
|
-
- More chains (currently Ethereum
|
|
522
|
+
- More chains (currently Ethereum Mainnet + Ethereum Sepolia + Polygon Mainnet)
|
|
368
523
|
- Support for validations
|
|
369
524
|
- Enhanced x402 payments
|
|
370
|
-
- Semantic/Vectorial search
|
|
371
525
|
- Advanced reputation aggregation
|
|
372
526
|
- Import/Export to centralized catalogues
|
|
373
527
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
agent0_sdk/__init__.py,sha256=l-IYzlB87rfM6Rigthoasgc80HmQ-BHHbJENZU6St6I,1190
|
|
2
|
+
agent0_sdk/core/agent.py,sha256=P3AX7zm4G5qkWdTJcjOvR69cCyOovHefbRoKejj6QKY,48062
|
|
3
|
+
agent0_sdk/core/contracts.py,sha256=EVxtxc5z6hI7p40Va5ibu0Pssmi6Y6UEG1_wfO7TZ_U,22942
|
|
4
|
+
agent0_sdk/core/endpoint_crawler.py,sha256=QBkFc3tBSQqHj6PtSTZ5D3_HVB00KJZJdxE3uYpI9po,13611
|
|
5
|
+
agent0_sdk/core/feedback_manager.py,sha256=rgQSxjNlEtBLN_bzQ1rnPL2kuaHCHM5vIEyw7Uitg3Q,42696
|
|
6
|
+
agent0_sdk/core/indexer.py,sha256=apXiAA-kYEcRMv6s8NgiguwinPs3cKihLZ4B8jqaPAE,75122
|
|
7
|
+
agent0_sdk/core/ipfs_client.py,sha256=17XXMpJgLWhcNUSkmduAZt409c8oJXlj9C_eTGVk-Io,14185
|
|
8
|
+
agent0_sdk/core/models.py,sha256=xZc93KKzsgc1cm0yymN2lFaMFv6MuaUNS9tcxT6Lktg,14383
|
|
9
|
+
agent0_sdk/core/oasf_validator.py,sha256=ZOtYYzQd7cJj3eJegi7Ch5ydoapJEjaJSxMvwzKSp5o,2980
|
|
10
|
+
agent0_sdk/core/sdk.py,sha256=TKagv6AufrCWFmfOa79yODa6--PP4tt5G8UCXWS59N0,27484
|
|
11
|
+
agent0_sdk/core/semantic_search_client.py,sha256=MrWMKmZ6qQhqKiIDiS2W5Aop4ak-YQ9VastIVlVzL0c,2013
|
|
12
|
+
agent0_sdk/core/subgraph_client.py,sha256=VBHSdMKIr-DLRKu0bGQMBC_fdxI8SgNMqVLpPWYuQc0,27374
|
|
13
|
+
agent0_sdk/core/transaction_handle.py,sha256=tKo6ny02m3eIeDGo0Wjikf-yUtl_8KYJy5YxFkPvyHo,1958
|
|
14
|
+
agent0_sdk/core/value_encoding.py,sha256=NQUUvjTRAr5Tqj8t4HUGlfhak8VDmB8E5WMlfAqJwVk,3311
|
|
15
|
+
agent0_sdk/core/web3_client.py,sha256=9w5ZgHILteCHSOisae3QluwuIsX3OD-VkoAc01koQWA,13786
|
|
16
|
+
agent0_sdk/taxonomies/all_domains.json,sha256=buM8_6mpY8_AMbBIPzM-gtu14Tl30QDmhuQxxrlJU4c,74625
|
|
17
|
+
agent0_sdk/taxonomies/all_skills.json,sha256=WVsutw3fqoj1jfDPru3CyWTr1kc1a5-EhBOWPfXnEi8,47483
|
|
18
|
+
agent0_sdk-1.5.1b1.dist-info/licenses/LICENSE,sha256=rhZZbZm_Ovz4Oa9LNQ-ms8a1tA36wWh90ZkC0OR7WMw,1072
|
|
19
|
+
agent0_sdk-1.5.1b1.dist-info/METADATA,sha256=srsv0FCyL6LWGo3zldnLEHVH-CQAXQ7lnAqSnRoIc_k,20216
|
|
20
|
+
agent0_sdk-1.5.1b1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
21
|
+
agent0_sdk-1.5.1b1.dist-info/top_level.txt,sha256=p4520WUKNfhU0lVWJgkrB_jdeUfvHSY3K18k4oYLNfI,11
|
|
22
|
+
agent0_sdk-1.5.1b1.dist-info/RECORD,,
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
agent0_sdk/__init__.py,sha256=NUCdspMGo80UwULYUXXvd6rCtwlnj0qhEA7fa_nMb5M,1102
|
|
2
|
-
agent0_sdk/core/agent.py,sha256=P3AX7zm4G5qkWdTJcjOvR69cCyOovHefbRoKejj6QKY,48062
|
|
3
|
-
agent0_sdk/core/contracts.py,sha256=o2e_2w8YnPlf-VVVI4s7VE7p39uSjj2zJ0gVXyMbeOM,22787
|
|
4
|
-
agent0_sdk/core/endpoint_crawler.py,sha256=QBkFc3tBSQqHj6PtSTZ5D3_HVB00KJZJdxE3uYpI9po,13611
|
|
5
|
-
agent0_sdk/core/feedback_manager.py,sha256=gHCyBYK17Yc5HcxDcbhl_blXYqulYO-7oiEvoPQomms,42585
|
|
6
|
-
agent0_sdk/core/indexer.py,sha256=gz4DDQQcRbe1RQtFSgq4OZLLFwXHFIe4v2-CcpD077A,72661
|
|
7
|
-
agent0_sdk/core/ipfs_client.py,sha256=17XXMpJgLWhcNUSkmduAZt409c8oJXlj9C_eTGVk-Io,14185
|
|
8
|
-
agent0_sdk/core/models.py,sha256=kiCtRm_ORdBph-Ces0HStsY92jnevY5yCpITb0PZErw,12218
|
|
9
|
-
agent0_sdk/core/oasf_validator.py,sha256=ZOtYYzQd7cJj3eJegi7Ch5ydoapJEjaJSxMvwzKSp5o,2980
|
|
10
|
-
agent0_sdk/core/sdk.py,sha256=w1Q6oCrQoXnCd9fgFlz1rOM0P1JbLYWAB8gs1Upz4IU,39510
|
|
11
|
-
agent0_sdk/core/subgraph_client.py,sha256=seEisw__r9nqQl1CgXa5DiUb6EvZ2GG7qS4wQPLILWo,29854
|
|
12
|
-
agent0_sdk/core/transaction_handle.py,sha256=tKo6ny02m3eIeDGo0Wjikf-yUtl_8KYJy5YxFkPvyHo,1958
|
|
13
|
-
agent0_sdk/core/value_encoding.py,sha256=NQUUvjTRAr5Tqj8t4HUGlfhak8VDmB8E5WMlfAqJwVk,3311
|
|
14
|
-
agent0_sdk/core/web3_client.py,sha256=9w5ZgHILteCHSOisae3QluwuIsX3OD-VkoAc01koQWA,13786
|
|
15
|
-
agent0_sdk/taxonomies/all_domains.json,sha256=buM8_6mpY8_AMbBIPzM-gtu14Tl30QDmhuQxxrlJU4c,74625
|
|
16
|
-
agent0_sdk/taxonomies/all_skills.json,sha256=WVsutw3fqoj1jfDPru3CyWTr1kc1a5-EhBOWPfXnEi8,47483
|
|
17
|
-
agent0_sdk-1.4.2.dist-info/licenses/LICENSE,sha256=rhZZbZm_Ovz4Oa9LNQ-ms8a1tA36wWh90ZkC0OR7WMw,1072
|
|
18
|
-
agent0_sdk-1.4.2.dist-info/METADATA,sha256=D6o0O1JHNKDkLLo3tv4NOvsz5A7LAf2Zrw44rtuh5u8,15222
|
|
19
|
-
agent0_sdk-1.4.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
20
|
-
agent0_sdk-1.4.2.dist-info/top_level.txt,sha256=p4520WUKNfhU0lVWJgkrB_jdeUfvHSY3K18k4oYLNfI,11
|
|
21
|
-
agent0_sdk-1.4.2.dist-info/RECORD,,
|