Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .claude/CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ Two identity paths: `X-Wallet-Address` (wallet-based) and `X-Operator-Token` (cr

## Methods (sync + async)

- `get_reputation` / `aget_reputation` — cached reputation lookup (free)
- `assess` / `aassess` — identity gate with policy (paid). Accepts `operator_token` for non-wallet agents. Response includes `linked_wallets[]` and `resolved_operator`. Optional `signer: { address, network }` opts into server-side wallet-signer-match AND OFAC SDN wallet-address screening — the response then carries both a `signer_match` block (wallet-binding verdict: `pass` / `wallet_signer_mismatch` / `wallet_auth_requires_wallet_signing`) and a `signer_sanctions` block (discriminated union: `{status: "clear"}` | `{sanctioned: True, ofac_label, sdn_uid, listed_at}` | `{status: "unavailable"}`). Wallet-OFAC SDN enforcement on the `signer` block is unconditional whenever a signer is supplied — no `policy.require_sanctions_clear` opt-in required. A `sanctioned: True` OR `status: "unavailable"` verdict flips the response `decision` to `deny` with `decision_reasons` including `sanctions_flagged` or `sanctions_check_unavailable` respectively (fail-closed; OFAC strict-liability). `policy.require_sanctions_clear` is the separate NAME-based screen on the resolved operator's KYC identity.
- `create_session` / `acreate_session` — create verification session. Returns `agent_memory` + `next_steps`.
- `poll_session` / `apoll_session` — poll session status, returns credential when verified, plus `next_steps.action`.
Expand Down
18 changes: 3 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ from agentscore import AgentScore

client = AgentScore(api_key="as_live_...")

# Look up cached reputation (free)
rep = client.get_reputation("0x1234...")
print(rep["score"]["value"], rep["score"]["grade"])

# Filter to a specific chain
base_rep = client.get_reputation("0x1234...", chain="base")

# Identity gate with policy (paid)
gated = client.assess(
"0x1234...",
Expand All @@ -38,10 +31,6 @@ gated = client.assess(
if gated["decision"] == "deny":
print(gated["decision_reasons"]) # ["kyc_required"]
print(gated.get("verify_url")) # URL for operator verification

# Check verification level
rep = client.get_reputation("0x1234...")
print(rep.get("verification_level")) # "none" | "wallet_claimed" | "kyc_verified"
```

### Credential-Based Identity
Expand Down Expand Up @@ -75,7 +64,7 @@ client.create_session(kind="sign_in") # registration-only: account sign-in, no

### Wallet resolution

`assess()` responses include `resolved_operator` and `linked_wallets`, all same-operator sibling wallets (claimed via SIWE or captured via prior `associate_wallet`). The list may mix EVM addresses (`0x...` lowercased) and Solana addresses (base58, case-preserved) for cross-chain operators; merchants doing wallet-signer-match checks should accept a payment signed by any address in the list, regardless of chain. The `address` parameter on `assess()` and `get_reputation()` accepts either format; the network is auto-detected from the address shape.
`assess()` responses include `resolved_operator` and `linked_wallets`, all same-operator sibling wallets (claimed via SIWE or captured via prior `associate_wallet`). The list may mix EVM addresses (`0x...` lowercased) and Solana addresses (base58, case-preserved) for cross-chain operators; merchants doing wallet-signer-match checks should accept a payment signed by any address in the list, regardless of chain. The `address` parameter on `assess()` accepts either format; the network is auto-detected from the address shape.

### Server-side signer-match + sanctions screening

Expand Down Expand Up @@ -138,7 +127,6 @@ All methods have async variants prefixed with `a`:

```python
async with AgentScore(api_key="as_live_...") as client:
rep = await client.aget_reputation("0x1234...")
result = await client.aassess("0x1234...", policy={"require_kyc": True})

# Identity model methods
Expand All @@ -158,7 +146,7 @@ async with AgentScore(api_key="as_live_...") as client:

```python
with AgentScore(api_key="as_live_...") as client:
rep = client.get_reputation("0x1234...")
result = client.assess("0x1234...")
```

## Configuration
Expand All @@ -178,7 +166,7 @@ with AgentScore(api_key="as_live_...") as client:
from agentscore import AgentScore, AgentScoreError

try:
rep = client.get_reputation("0xinvalid")
result = client.assess("0xinvalid")
except AgentScoreError as e:
print(e.code, e.status_code, str(e))
```
Expand Down
32 changes: 0 additions & 32 deletions agentscore/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,12 @@
from agentscore.test_mode import AGENTSCORE_TEST_ADDRESSES, is_agentscore_test_address
from agentscore.types import (
AccountVerification,
Activity,
AgentMemoryHint,
AgentMemoryIdentityPaths,
AgentSummary,
AipProvenance,
AipSignatureMaterial,
AssessResponse,
AssociateWalletResponse,
ChainEntry,
ChainScore,
Classification,
CredentialCreateErrorNextSteps,
CredentialCreateErrorResponse,
CredentialCreateResponse,
Expand All @@ -32,23 +27,13 @@
CredentialRevokeResponse,
DecisionPolicy,
DenialCode,
EntityType,
EvidenceSummary,
Grade,
Identity,
Network,
NextStepsAction,
OperatorScore,
OperatorVerification,
PolicyCheck,
PolicyExplanation,
PolicyResult,
QuotaInfo,
RedactedClassification,
Reputation,
ReputationResponse,
ReputationStatus,
Score,
SessionCreateNextSteps,
SessionCreateRequest,
SessionCreateResponse,
Expand All @@ -60,7 +45,6 @@
SignerSanctionsClear,
SignerSanctionsHit,
SignerSanctionsUnavailable,
Subject,
VerificationLevel,
WalletAuthRequiresSigningBody,
WalletAuthRequiresSigningNextSteps,
Expand All @@ -73,19 +57,14 @@
__all__ = [
"AGENTSCORE_TEST_ADDRESSES",
"AccountVerification",
"Activity",
"AgentMemoryHint",
"AgentMemoryIdentityPaths",
"AgentScore",
"AgentScoreError",
"AgentSummary",
"AipProvenance",
"AipSignatureMaterial",
"AssessResponse",
"AssociateWalletResponse",
"ChainEntry",
"ChainScore",
"Classification",
"CredentialCreateErrorNextSteps",
"CredentialCreateErrorResponse",
"CredentialCreateResponse",
Expand All @@ -94,14 +73,9 @@
"CredentialRevokeResponse",
"DecisionPolicy",
"DenialCode",
"EntityType",
"EvidenceSummary",
"Grade",
"Identity",
"InvalidCredentialError",
"Network",
"NextStepsAction",
"OperatorScore",
"OperatorVerification",
"PaymentRequiredError",
"PolicyCheck",
Expand All @@ -110,11 +84,6 @@
"QuotaExceededError",
"QuotaInfo",
"RateLimitedError",
"RedactedClassification",
"Reputation",
"ReputationResponse",
"ReputationStatus",
"Score",
"SessionCreateNextSteps",
"SessionCreateRequest",
"SessionCreateResponse",
Expand All @@ -126,7 +95,6 @@
"SignerSanctionsClear",
"SignerSanctionsHit",
"SignerSanctionsUnavailable",
"Subject",
"TimeoutError",
"TokenExpiredError",
"VerificationLevel",
Expand Down
17 changes: 0 additions & 17 deletions agentscore/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ def _build_error_from_response(response: httpx.Response) -> AgentScoreError:
CredentialRevokeResponse,
DecisionPolicy,
Network,
ReputationResponse,
SessionCreateResponse,
SessionPollResponse,
Signer,
Expand Down Expand Up @@ -247,14 +246,6 @@ def _handle_response(self, response: httpx.Response) -> Any:

# --- Sync methods ---

def get_reputation(self, address: str, chain: str | None = None) -> ReputationResponse:
"""Get cached reputation for an address (free, read-only). Optionally filter by chain."""
params: dict[str, str] = {}
if chain:
params["chain"] = chain
client = self._get_sync_client()
return self._send_sync(lambda: client.get(f"/v1/reputation/{address}", params=params))

def assess(
self,
address: str | None = None,
Expand Down Expand Up @@ -404,14 +395,6 @@ def associate_wallet(

# --- Async methods ---

async def aget_reputation(self, address: str, chain: str | None = None) -> ReputationResponse:
"""Get cached reputation for an address (free, read-only). Optionally filter by chain."""
params: dict[str, str] = {}
if chain:
params["chain"] = chain
client = self._get_async_client()
return await self._send_async(lambda: client.get(f"/v1/reputation/{address}", params=params))

async def aassess(
self,
address: str | None = None,
Expand Down
135 changes: 0 additions & 135 deletions agentscore/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,144 +2,9 @@

from typing import Literal, NotRequired, TypedDict

Grade = Literal["A", "B", "C", "D", "F"]
EntityType = Literal["agent", "service", "hybrid", "wallet", "bot", "unknown", "individual", "entity"]
ReputationStatus = Literal["scored", "stale", "known_unscored"]
VerificationLevel = Literal["none", "wallet_claimed", "kyc_verified"]


class _SubjectRequired(TypedDict):
chains: list[str]


class Subject(_SubjectRequired, total=False):
address: str
credential_prefix: str


class Classification(TypedDict):
entity_type: EntityType
confidence: float | None
is_known: bool
is_known_erc8004_agent: bool
has_candidate_payment_activity: bool
has_verified_payment_activity: bool
reasons: list[str]


class Score(TypedDict):
value: float | None
grade: Grade | None
scored_at: str | None
status: ReputationStatus
version: str


class _ChainScoreRequired(TypedDict):
value: float | None
grade: Grade | None
scored_at: str | None
status: ReputationStatus
version: str


class ChainScore(_ChainScoreRequired, total=False):
confidence: float | None
dimensions: dict[str, float] | None


class Identity(TypedDict):
ens_name: str | None
website_url: str | None
github_url: str | None


class Activity(TypedDict):
total_candidate_transactions: int
total_verified_transactions: int
as_candidate_payer: int
as_candidate_payee: int
as_verified_payer: int
as_verified_payee: int
counterparties_count: int
active_days: int
active_months: int
first_candidate_tx_at: str | None
last_candidate_tx_at: str | None
first_verified_tx_at: str | None
last_verified_tx_at: str | None


class Reputation(TypedDict):
feedback_count: int
client_count: int
trust_avg: float | None
uptime_avg: float | None
activity_avg: float | None
last_feedback_at: str | None


class EvidenceSummary(TypedDict):
metadata_kind: str | None
has_a2a_agent_card: bool
website_url: str | None
website_reachable: bool
website_mentions_mcp: bool
website_mentions_x402: bool
github_url: str | None
github_stars: int | None


class RedactedClassification(TypedDict):
entity_type: EntityType


class _OperatorScoreRequired(TypedDict):
score: float
grade: Grade


class OperatorScore(_OperatorScoreRequired, total=False):
agent_count: int
chains_active: list[str]


class AgentSummary(TypedDict):
token_id: int
chain: str
name: str | None
score: float
grade: Grade


class _ChainEntryRequired(TypedDict):
chain: str
score: ChainScore
classification: Classification | RedactedClassification


class ChainEntry(_ChainEntryRequired, total=False):
identity: Identity
activity: Activity
evidence_summary: EvidenceSummary


class _ReputationResponseRequired(TypedDict):
subject: Subject
score: Score
chains: list[ChainEntry]
data_semantics: str
caveats: list[str]
updated_at: str | None


class ReputationResponse(_ReputationResponseRequired, total=False):
reputation: Reputation
operator_score: OperatorScore
agents: list[AgentSummary]
verification_level: VerificationLevel


class _OperatorVerificationRequired(TypedDict):
level: VerificationLevel

Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ build-backend = "hatchling.build"

[project]
name = "agentscore-py"
version = "2.6.11"
version = "3.0.0"
description = "Python client for the AgentScore APIs"
readme = "README.md"
license = "MIT"
requires-python = ">=3.11"
keywords = ["agentscore", "x402", "erc-8004", "agent", "trust", "reputation", "wallet", "blockchain", "ai-agent", "agentic-payments"]
keywords = ["agentscore", "x402", "erc-8004", "agent", "trust", "wallet", "blockchain", "ai-agent", "agentic-payments"]
dependencies = [
"httpx>=0.25.0,<1.0.0",
]
Expand Down
Loading
Loading