feat: typed assess errors + X-Quota headers + signer_match types (python parity)#21
Merged
vvillait88 merged 8 commits intomainfrom May 2, 2026
Merged
Conversation
…er_match
Parity with @agent-score/sdk equivalent change:
- New error subclasses (all subclass AgentScoreError so existing catches still work):
PaymentRequiredError (402), TokenExpiredError (401 token_expired with parsed body
fields exposed: verify_url/session_id/poll_secret/poll_url/next_steps/agent_memory),
InvalidCredentialError (401 invalid_credential), QuotaExceededError (429 quota_exceeded),
RateLimitedError (429 rate_limited), TimeoutError (httpx.TimeoutException wrapped)
- AssessResponse gains optional quota field { limit, used, reset } captured from
X-Quota-Limit / X-Quota-Used / X-Quota-Reset response headers
- New telemetry_signer_match / atelemetry_signer_match methods — fire-and-forget POST
to /v1/telemetry/signer-match
- Internal: _send_sync_with_response / _send_async_with_response variants expose the
raw httpx.Response so assess() can read response headers; shared
_build_error_from_response helper does status+code routing once
- All typed errors + QuotaInfo exported from agentscore.__init__
Backward-compatible: all new error classes inherit AgentScoreError; existing
except AgentScoreError blocks unaffected. New quota field is optional (NotRequired).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit caught a regression: `_send_sync` / `_send_async` only wrapped `httpx.TimeoutException` into our typed TimeoutError. Other httpx errors (ConnectError, NetworkError, ProtocolError) propagated unwrapped, breaking the "all SDK errors are AgentScoreError subclasses" contract callers rely on. - New `_do_sync` / `_do_async` helpers wrap every `httpx.HTTPError` into AgentScoreError(code='network_error', status_code=0); `httpx.TimeoutException` specifically becomes our TimeoutError. Matches node-sdk's catch-all in `request<T>`. - Updated `test_connect_error_raises_agentscore_error` to match the new contract (was misnamed — asserted raw httpx.ConnectError previously). Docs: - README: "Typed error classes" subsection with class table; quota-observability + telemetry sections; explicit note about TimeoutError shadowing the builtin (import explicitly from agentscore.errors). - CLAUDE.md: new methods listed; new "Errors + observability" section. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures TEC-274 minor: new public exports (PaymentRequiredError, TokenExpiredError, InvalidCredentialError, QuotaExceededError, RateLimitedError, TimeoutError) + AssessResponse.quota field + telemetry_signer_match methods. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mpty-body Mirror of the node-sdk edge-case tests just added. All paths the audit flagged as "behavior correct, not tested": - assess captures quota from retry response on 429 → 200 (not the 429). - 400 invalid_request falls through to generic AgentScoreError (no typed subclass match). Type check uses `type(err) is AgentScoreError` to prove exactly the base class. - 401 token_expired with empty body — TokenExpiredError instance fields stay None, error is still TokenExpiredError. - 401 token_expired with wrong-typed body (number for verify_url) — fields stay None, raw values preserved in details. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…h assess/aassess Add ResolveSigner request type and SignerMatch response type matching the API's new server-side wallet-signer-match. assess() / aassess() gain an optional resolve_signer parameter; AssessResponse gains optional signer_match. Drop vestigial on_the_fly + updated_at fields from AssessResponse — they were never read by any caller. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Parity with how every other type in the package is exposed via agentscore/__init__.py — without this, consumers had to do `from agentscore.types import ResolveSigner` instead of the documented `from agentscore import ResolveSigner`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
AssessErrortaxonomy mirroring node-sdk so consumers can branch on denial codes without string parsingX-Quota-Limit/X-Quota-Used/X-Quota-Resetheaders onAssessResponseResolveSignerrequest type +SignerMatchresponse type for server-side signer matching on/v1/assess(TEC-263 SDK side)telemetry_signer_match()method (sync + async) for posting gate-side outcomesCloses TEC-274.
Test plan
uv run pytest)--cov-fail-under=95)uv buildproduces clean wheel🤖 Generated with Claude Code