Metadata-Version: 2.4
Name: agentberlin
Version: 0.14.0
Summary: Python SDK for Agent Berlin - AI-powered SEO and AEO automation
Project-URL: Homepage, https://agentberlin.ai
Project-URL: Documentation, https://docs.agentberlin.ai/sdk/python
Project-URL: Repository, https://github.com/boat-builder/berlin
Author-email: Agent Berlin <support@agentberlin.ai>
License: MIT
License-File: LICENSE
Keywords: aeo,ai,analytics,optimization,search,seo
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: pydantic>=2.0.0
Requires-Dist: requests>=2.28.0
Provides-Extra: dev
Requires-Dist: black>=24.0.0; extra == 'dev'
Requires-Dist: isort>=5.13.0; extra == 'dev'
Requires-Dist: mypy>=1.8.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Requires-Dist: responses>=0.25.0; extra == 'dev'
Requires-Dist: types-requests>=2.31.0; extra == 'dev'
Description-Content-Type: text/markdown

# Agent Berlin Python SDK

Official Python SDK for [Agent Berlin](https://agentberlin.ai) - AI-powered SEO and AEO automation.

## Installation

```bash
pip install agentberlin
```

## Quick Start

```python
from agentberlin import AgentBerlin

client = AgentBerlin()

# Get analytics for your project
analytics = client.analytics.get(project_domain="example.com")
print(f"Visibility: {analytics.visibility.current_percentage}%")
print(f"LLM Sessions: {analytics.traffic.llm_sessions}")

# Search for pages
pages = client.pages.search(
    project_domain="example.com",
    query="SEO best practices",
    limit=10
)
for page in pages.pages:
    print(f"  - {page.title}: {page.url}")

# Search for keywords
keywords = client.keywords.search(
    project_domain="example.com",
    query="digital marketing"
)
for kw in keywords.keywords:
    print(f"  - {kw.keyword} (volume: {kw.volume})")

# Get page details
page = client.pages.get(
    project_domain="example.com",
    url="https://example.com/blog/seo-tips"
)
print(f"Title: {page.title}")
print(f"H1: {page.h1}")

# Get brand profile
profile = client.brand.get_profile(project_domain="example.com")
print(f"Domain Authority: {profile.domain_authority}")

# Update brand profile
client.brand.update_profile(
    project_domain="example.com",
    field="competitors",
    value="competitor.com",
    mode="add"
)

# Fetch SERP results
serp = client.serp.fetch(query="best seo tools", max_results=5)
for result in serp.results:
    print(f"  - {result.title}: {result.url}")
```

## Configuration

```python
client = AgentBerlin(
    token="your-token",           # Optional if AGENTBERLIN_TOKEN env var is set
    base_url="https://...",       # Optional, defaults to production API
    timeout=30,                   # Request timeout in seconds
)
```

## Error Handling

```python
from agentberlin import AgentBerlin
from agentberlin.exceptions import (
    AgentBerlinError,
    AgentBerlinAuthenticationError,
    AgentBerlinNotFoundError,
    AgentBerlinRateLimitError,
)

client = AgentBerlin()

try:
    analytics = client.analytics.get(project_domain="example.com")
except AgentBerlinAuthenticationError:
    print("Invalid or missing API token")
except AgentBerlinNotFoundError:
    print("Domain not found")
except AgentBerlinRateLimitError as e:
    print(f"Rate limited. Retry after {e.retry_after} seconds")
except AgentBerlinError as e:
    print(f"API error: {e.message}")
```

---

# Workflow Script API Documentation

This section provides detailed API documentation for writing workflow scripts. When writing workflow scripts, you have access to the 'agentberlin' package which is pre-installed in the execution environment.

## Important Notes for Script Writers

1. The SDK client is available as a global variable 'client' - you don't need to initialize it
2. The project domain is available as a global variable 'PROJECT_DOMAIN'
3. Optional input from the LLM is available as the 'INPUT' variable (may be None or a parsed JSON value)
4. Scripts should print their results or return values that can be captured
5. Use proper error handling with try/except blocks

## Available Resources and Methods

### 1. Analytics Resource
Get comprehensive analytics data for the project.

```python
# Get analytics for the project
analytics = client.analytics.get(project_domain=PROJECT_DOMAIN)

# Available fields:
# analytics.domain - The domain name
# analytics.domain_authority - Domain authority score (0-100)
# analytics.visibility.current_percentage - Current visibility percentage
# analytics.visibility.ranking_stability - Ranking stability score
# analytics.visibility.share_of_voice - Share of voice percentage
# analytics.visibility.history - List of VisibilityPoint(date, percentage)
# analytics.traffic.total_sessions - Total traffic sessions
# analytics.traffic.llm_sessions - Sessions from LLM sources
# analytics.traffic.channel_breakdown.direct - Direct traffic
# analytics.traffic.channel_breakdown.organic_search - Organic search traffic
# analytics.traffic.channel_breakdown.referral - Referral traffic
# analytics.traffic.channel_breakdown.organic_social - Social traffic
# analytics.traffic.channel_breakdown.llm - LLM-referred traffic
# analytics.traffic.daily_trend - List of DailyTraffic(date, sessions, llm_sessions)
# analytics.topics - List of TopicSummary(name, appearances, avg_position, topical_authority, trend)
# analytics.competitors - List of CompetitorSummary(name, visibility, share_of_voice)
# analytics.data_range.start - Data start date
# analytics.data_range.end - Data end date
# analytics.last_updated - Last update timestamp
```

### 2. Pages Resource
Search and get detailed information about pages.

```python
# Search for pages
pages = client.pages.search(
    project_domain=PROJECT_DOMAIN,
    query="SEO best practices",  # Semantic search query
    limit=10,                     # Max results (default: 10)
    domain=None,                  # Optional: filter by specific domain
    status_code=None,             # Optional: filter by HTTP status code
    topic=None,                   # Optional: filter by topic
    page_type=None                # Optional: "pillar" or "landing"
)
# Returns: PageSearchResponse with pages list and total count
# Each page has: url, title

# Get detailed page information
page = client.pages.get(
    project_domain=PROJECT_DOMAIN,
    url="https://example.com/blog/article",
    content_length=500  # Optional: include content preview (0 = no content)
)
# Returns PageDetailResponse with:
# page.url - Page URL
# page.title - Page title
# page.meta_description - Meta description
# page.h1 - H1 heading
# page.domain - Domain name
# page.links.inlinks - List of incoming links (PageLink objects)
# page.links.outlinks - List of outgoing links (PageLink objects)
# page.topic_info.topics - List of topic names
# page.topic_info.topic_scores - List of topic relevance scores
# page.topic_info.page_type - "pillar" or "landing"
# page.topic_info.assigned_topic - Primary assigned topic
# page.content_preview - Content preview (if content_length > 0)
# page.content_length - Total content length
```

### 3. Keywords Resource
Search for keywords with SEO metrics.

```python
# Search for keywords
keywords = client.keywords.search(
    project_domain=PROJECT_DOMAIN,
    query="digital marketing",  # Semantic search query
    limit=10                    # Max results (default: 10)
)
# Returns KeywordSearchResponse with keywords list and total count
# Each keyword has:
# keyword.keyword - The keyword text
# keyword.volume - Monthly search volume
# keyword.difficulty - Difficulty score (0-100)
# keyword.cpc - Cost per click
# keyword.intent - Search intent: "informational", "commercial", "transactional", "navigational"
```

### 4. Brand Resource
Get and update brand profile information.

```python
# Get brand profile
profile = client.brand.get_profile(project_domain=PROJECT_DOMAIN)
# Returns BrandProfileResponse with:
# profile.domain - Domain name
# profile.name - Brand name
# profile.context - Brand context/description
# profile.search_analysis_context - Search analysis context
# profile.domain_authority - Domain authority score
# profile.competitors - List of competitor domains
# profile.industries - List of industries
# profile.business_models - List of business models
# profile.company_size - Company size
# profile.target_customer_segments - Target segments
# profile.geographies - Target geographies
# profile.personas - Target personas
# profile.sitemaps - Sitemap URLs
# profile.profile_urls - Profile URLs

# Update brand profile
client.brand.update_profile(
    project_domain=PROJECT_DOMAIN,
    field="competitors",  # Field to update
    value="competitor.com",  # New value
    mode="add"  # "add" to append, "set" to replace
)
# Valid fields: name, context, competitors, industries, business_models,
#               company_size, target_segments, geographies, personas
```

### 5. SERP Resource
Fetch Google search results.

```python
# Fetch SERP results
serp = client.serp.fetch(
    query="best seo tools",
    max_results=10,      # Max results (default: 10)
    country="US",        # Optional: ISO 3166-1 country code
    language="lang_en"   # Optional: ISO 639-1 with "lang_" prefix
)
# Returns SERPResponse with:
# serp.query - The search query
# serp.results - List of SERPResult objects
# serp.total - Total results count
# Each result has: title, url, snippet
```

## Example Script Patterns

### Pattern 1: Data Retrieval Script
```python
# Retrieves and formats analytics data
import json

analytics = client.analytics.get(project_domain=PROJECT_DOMAIN)

result = {
    "visibility": analytics.visibility.current_percentage,
    "traffic": analytics.traffic.total_sessions,
    "llm_traffic": analytics.traffic.llm_sessions,
    "top_topics": [
        {"name": t.name, "authority": t.topical_authority}
        for t in analytics.topics[:5]
    ]
}
print(json.dumps(result, indent=2))
```

### Pattern 2: Search and Analysis Script
```python
# Searches for content opportunities
import json

query = INPUT.get("query", "SEO tips") if INPUT else "SEO tips"
pages = client.pages.search(project_domain=PROJECT_DOMAIN, query=query, limit=20)
keywords = client.keywords.search(project_domain=PROJECT_DOMAIN, query=query, limit=20)

opportunities = []
for kw in keywords.keywords:
    if kw.difficulty and kw.difficulty < 50 and kw.volume and kw.volume > 100:
        opportunities.append({
            "keyword": kw.keyword,
            "volume": kw.volume,
            "difficulty": kw.difficulty
        })

print(json.dumps({"opportunities": opportunities}, indent=2))
```

### Pattern 3: Competitive Analysis Script
```python
# Analyzes competitors from SERP
import json

query = INPUT.get("query") if INPUT else "best seo software"
serp = client.serp.fetch(query=query, max_results=10)
profile = client.brand.get_profile(project_domain=PROJECT_DOMAIN)

competitor_presence = []
for result in serp.results:
    is_competitor = any(comp in result.url for comp in profile.competitors)
    is_own = PROJECT_DOMAIN in result.url
    competitor_presence.append({
        "url": result.url,
        "title": result.title,
        "is_competitor": is_competitor,
        "is_own": is_own
    })

print(json.dumps(competitor_presence, indent=2))
```
