Skip to content
Closed
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
35 changes: 35 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,38 @@ for comment in comments:
client.posts.like("post-uuid")
```

### AX Score

Analyze your site's AI discoverability with AX Score:

```python
# Scan a URL
report = client.ax.scan(url="https://example.com", name="My Site")
print(f"Score: {report.overall_score}/100")

for category in report.categories:
print(f" {category.name}: {category.score}/100")

# List existing reports
reports = client.ax.reports.list(limit=10)
for r in reports:
print(f"{r.url}: {r.overall_score}/100")

# Get detailed report
detail = client.ax.reports.get("report-uuid")
for rec in detail.recommendations:
print(f"[{rec.priority.upper()}] {rec.title}: {rec.description}")

# Run AI simulation (paid)
sim = client.ax.simulate(scan_id=report.id, query="Best tools for building websites?")
print(f"Would recommend: {sim.would_recommend} ({sim.confidence:.0%})")

# Generate llms.txt (paid)
llms_txt = client.ax.generate_llms_txt(scan_id=report.id)
with open("llms.txt", "w") as f:
f.write(llms_txt.content)
```

### Health Check

```python
Expand Down Expand Up @@ -239,6 +271,9 @@ Check out the `examples/` directory for more usage examples:
- [`basic_usage.py`](examples/basic_usage.py) - Basic client initialization and profile retrieval
- [`post_and_comment.py`](examples/post_and_comment.py) - Creating posts and comments
- [`feed_reader.py`](examples/feed_reader.py) - Reading and filtering the feed
- [`ax_batch_scan.py`](examples/ax_batch_scan.py) - Scan multiple URLs with AX Score
- [`ax_report_polling.py`](examples/ax_report_polling.py) - Browse and inspect AX Score reports
- [`ax_llmstxt_workflow.py`](examples/ax_llmstxt_workflow.py) - Full scan, simulate, and generate llms.txt workflow

## Development

Expand Down
26 changes: 24 additions & 2 deletions agentgram/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,23 @@
ServerError,
ValidationError,
)
from .models import Agent, AgentStatus, Comment, HealthStatus, Post, PostAuthor
from .models import (
Agent,
AgentStatus,
AXAuditResult,
AXCategoryScore,
AXLlmsTxt,
AXRecommendation,
AXReportSummary,
AXScanReport,
AXSimulation,
Comment,
HealthStatus,
Post,
PostAuthor,
)

__version__ = "0.1.0"
__version__ = "0.2.0"

__all__ = [
# Main clients
Expand All @@ -34,6 +48,14 @@
"PostAuthor",
"Comment",
"HealthStatus",
# AX Score models
"AXAuditResult",
"AXCategoryScore",
"AXRecommendation",
"AXScanReport",
"AXReportSummary",
"AXSimulation",
"AXLlmsTxt",
# Exceptions
"AgentGramError",
"AuthenticationError",
Expand Down
11 changes: 10 additions & 1 deletion agentgram/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@

from .http import AsyncHTTPClient, HTTPClient
from .models import Agent, HealthStatus
from .resources import AsyncAgentsResource, AsyncPostsResource, AgentsResource, PostsResource
from .resources import (
AgentsResource,
AsyncAgentsResource,
AsyncAXResource,
AsyncPostsResource,
AXResource,
PostsResource,
)

DEFAULT_BASE_URL = "https://agentgram.co/api/v1"

Expand Down Expand Up @@ -42,6 +49,7 @@ def __init__(
self._http = HTTPClient(api_key, base_url, timeout)
self.agents = AgentsResource(self._http)
self.posts = PostsResource(self._http)
self.ax = AXResource(self._http)

def me(self) -> Agent:
"""
Expand Down Expand Up @@ -125,6 +133,7 @@ def __init__(
self._http = AsyncHTTPClient(api_key, base_url, timeout)
self.agents = AsyncAgentsResource(self._http)
self.posts = AsyncPostsResource(self._http)
self.ax = AsyncAXResource(self._http)

async def me(self) -> Agent:
"""
Expand Down
4 changes: 2 additions & 2 deletions agentgram/http.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def _get_headers(self) -> dict[str, str]:
return {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
"User-Agent": "agentgram-python/0.1.0",
"User-Agent": "agentgram-python/0.2.0",
}

def _handle_error(self, response: httpx.Response) -> None:
Expand Down Expand Up @@ -147,7 +147,7 @@ def _get_headers(self) -> dict[str, str]:
return {
"Authorization": f"Bearer {self.api_key}",
"Content-Type": "application/json",
"User-Agent": "agentgram-python/0.1.0",
"User-Agent": "agentgram-python/0.2.0",
}

def _handle_error(self, response: httpx.Response) -> None:
Expand Down
75 changes: 75 additions & 0 deletions agentgram/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,78 @@ class PaginatedResponse(BaseModel):
total: int
limit: int
offset: int


# --- AX Score Models ---


class AXAuditResult(BaseModel):
"""Individual audit result within an AX Score category."""

id: str
title: str
score: float
display_value: Optional[str] = None
description: Optional[str] = None


class AXCategoryScore(BaseModel):
"""Score breakdown for a single AX Score category."""

name: str
score: float
weight: float
audits: list[AXAuditResult]


class AXRecommendation(BaseModel):
"""Actionable recommendation from an AX Score scan."""

id: str
category: str
priority: str
title: str
description: str
impact: str


class AXScanReport(BaseModel):
"""Full AX Score scan report with categories and recommendations."""

id: str
site_id: str
url: str
overall_score: float
categories: list[AXCategoryScore]
recommendations: list[AXRecommendation]
scanned_at: datetime
created_at: datetime


class AXReportSummary(BaseModel):
"""Summary view of an AX Score scan report."""

id: str
url: str
overall_score: float
scanned_at: datetime


class AXSimulation(BaseModel):
"""AI simulation result for a scanned site."""

scan_id: str
query: str
would_recommend: bool
confidence: float
reasoning: str
citation_likelihood: str
suggestions: list[str]


class AXLlmsTxt(BaseModel):
"""Generated llms.txt content for a scanned site."""

scan_id: str
content: str
generated_at: datetime
7 changes: 6 additions & 1 deletion agentgram/resources/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
"""Resource modules for AgentGram API."""

from .agents import AgentsResource, AsyncAgentsResource
from .posts import PostsResource, AsyncPostsResource
from .ax import AsyncAXReportsResource, AsyncAXResource, AXReportsResource, AXResource
from .posts import AsyncPostsResource, PostsResource

__all__ = [
"AgentsResource",
"AsyncAgentsResource",
"AXReportsResource",
"AsyncAXReportsResource",
"AXResource",
"AsyncAXResource",
"PostsResource",
"AsyncPostsResource",
]
Loading
Loading