From ac5b71ac41a323a89bc6df47201bf27300a321be Mon Sep 17 00:00:00 2001 From: vvillait88 Date: Mon, 20 Apr 2026 19:07:13 -0700 Subject: [PATCH 1/2] feat: add user_agent parameter for attribution Optional user_agent on AgentScore is prepended to the default User-Agent as "{user_agent} (agentscore-py/{version})" so API calls from consumer apps can be attributed downstream. Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 11 ++++++----- agentscore/client.py | 5 ++++- tests/test_client.py | 15 +++++++++++++++ uv.lock | 2 +- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 4c58d9b..ec7989a 100644 --- a/README.md +++ b/README.md @@ -99,11 +99,12 @@ with AgentScore(api_key="as_live_...") as client: ## Configuration -| Parameter | Default | Description | -|------------|----------------------------|--------------------------| -| `api_key` | `None` | API key from [agentscore.sh](https://agentscore.sh) | -| `base_url` | `https://api.agentscore.sh` | API base URL | -| `timeout` | `10.0` | Request timeout (seconds)| +| Parameter | Default | Description | +|---------------|-----------------------------|--------------------------| +| `api_key` | `None` | API key from [agentscore.sh](https://agentscore.sh) | +| `base_url` | `https://api.agentscore.sh` | API base URL | +| `timeout` | `10.0` | Request timeout (seconds)| +| `user_agent` | `None` | Prepended to the default `User-Agent` as `"{user_agent} (agentscore-py/{version})"`. Use to attribute API calls to your app. | ## Error Handling diff --git a/agentscore/client.py b/agentscore/client.py index a0688f7..a733e0d 100644 --- a/agentscore/client.py +++ b/agentscore/client.py @@ -27,12 +27,15 @@ def __init__( api_key: str, base_url: str = "https://api.agentscore.sh", timeout: float = 10.0, + user_agent: str | None = None, ): if not api_key: raise ValueError("AgentScore API key is required. Get one at https://agentscore.sh/sign-up") self.api_key = api_key self.base_url = base_url.rstrip("/") self.timeout = timeout + default_ua = f"agentscore-py/{_pkg_version('agentscore-py')}" + self.user_agent = f"{user_agent} ({default_ua})" if user_agent else default_ua self._sync_client: httpx.Client | None = None self._async_client: httpx.AsyncClient | None = None @@ -40,7 +43,7 @@ def _headers(self) -> dict: return { "Accept": "application/json", "X-API-Key": self.api_key, - "User-Agent": f"agentscore-py/{_pkg_version('agentscore-py')}", + "User-Agent": self.user_agent, } def _get_sync_client(self) -> httpx.Client: diff --git a/tests/test_client.py b/tests/test_client.py index 83e6930..c8a691f 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -386,6 +386,21 @@ def test_user_agent_header_includes_version(): assert request.headers["user-agent"] == f"agentscore-py/{version('agentscore-py')}" +@respx.mock +def test_user_agent_header_prepends_custom_user_agent(): + """Custom user_agent should be rendered as '{custom} ({default})'.""" + from importlib.metadata import version + + respx.get(f"{BASE_URL}/v1/reputation/{ADDRESS}").mock( + return_value=httpx.Response(200, json=REPUTATION_PAYLOAD), + ) + client = AgentScore(api_key=API_KEY, user_agent="my-app/1.2.3") + client.get_reputation(ADDRESS) + request = respx.calls[0].request + expected = f"my-app/1.2.3 (agentscore-py/{version('agentscore-py')})" + assert request.headers["user-agent"] == expected + + # --------------------------------------------------------------------------- # Edge cases # --------------------------------------------------------------------------- diff --git a/uv.lock b/uv.lock index df1a47b..43a9158 100644 --- a/uv.lock +++ b/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ [[package]] name = "agentscore-py" -version = "1.5.0" +version = "1.6.0" source = { editable = "." } dependencies = [ { name = "httpx" }, From 76cdd5ddbf1287d9a25cb6c9a05097c82b4d7aa8 Mon Sep 17 00:00:00 2001 From: vvillait88 Date: Mon, 20 Apr 2026 19:27:11 -0700 Subject: [PATCH 2/2] chore: bump to 1.7.0 for user_agent attribution release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The default User-Agent "agentscore-py/{version}" already matches the PyPI install identifier, so only the version bumps — no UA rename needed in this package. Co-Authored-By: Claude Opus 4.7 (1M context) --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 88b5669..205e3e2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "agentscore-py" -version = "1.6.0" +version = "1.7.0" description = "Python client for the AgentScore trust and reputation API" readme = "README.md" license = "MIT" diff --git a/uv.lock b/uv.lock index 43a9158..2618f39 100644 --- a/uv.lock +++ b/uv.lock @@ -8,7 +8,7 @@ resolution-markers = [ [[package]] name = "agentscore-py" -version = "1.6.0" +version = "1.7.0" source = { editable = "." } dependencies = [ { name = "httpx" },