Metadata-Version: 2.4
Name: agenticstar-platform
Version: 0.5.14
Summary: AGENTICSTAR Platform SDK - Enterprise AI Agent Infrastructure
Project-URL: Homepage, https://developers.fd.agenticstar.tm.softbank.jp/
Project-URL: Documentation, https://developers.fd.agenticstar.tm.softbank.jp/
Project-URL: Repository, https://github.com/softbank/agenticstar-platform
Project-URL: Developer Portal, https://developers.fd.agenticstar.tm.softbank.jp/
Author-email: "SoftBank Corp." <agenticai@softbank.co.jp>
License-Expression: MIT
License-File: LICENSE
Keywords: agent,ai,enterprise,llm,rag,vector-database
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Requires-Python: >=3.11
Requires-Dist: httpx>=0.26.0
Provides-Extra: all
Requires-Dist: asyncpg>=0.29.0; extra == 'all'
Requires-Dist: azure-identity>=1.15.0; extra == 'all'
Requires-Dist: azure-storage-blob>=12.19.0; extra == 'all'
Requires-Dist: boto3>=1.34.0; extra == 'all'
Requires-Dist: google-cloud-storage>=2.14.0; extra == 'all'
Requires-Dist: mem0ai>=1.0.0; extra == 'all'
Requires-Dist: openai>=1.0.0; extra == 'all'
Requires-Dist: qdrant-client>=1.7.0; extra == 'all'
Provides-Extra: db
Requires-Dist: asyncpg>=0.29.0; extra == 'db'
Requires-Dist: azure-identity>=1.15.0; extra == 'db'
Provides-Extra: dev
Requires-Dist: mypy>=1.7.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.1.0; extra == 'dev'
Requires-Dist: pytest>=7.4.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: memory
Requires-Dist: mem0ai>=1.0.0; extra == 'memory'
Provides-Extra: rag
Requires-Dist: openai>=1.0.0; extra == 'rag'
Requires-Dist: qdrant-client>=1.7.0; extra == 'rag'
Provides-Extra: security
Requires-Dist: google-cloud-dlp>=3.12.0; extra == 'security'
Requires-Dist: httpx>=0.26.0; extra == 'security'
Provides-Extra: storage
Requires-Dist: azure-storage-blob>=12.19.0; extra == 'storage'
Requires-Dist: boto3>=1.34.0; extra == 'storage'
Requires-Dist: google-cloud-storage>=2.14.0; extra == 'storage'
Provides-Extra: storage-aws
Requires-Dist: boto3>=1.34.0; extra == 'storage-aws'
Provides-Extra: storage-azure
Requires-Dist: azure-storage-blob>=12.19.0; extra == 'storage-azure'
Provides-Extra: storage-gcp
Requires-Dist: google-cloud-storage>=2.14.0; extra == 'storage-gcp'
Description-Content-Type: text/markdown

# AGENTICSTAR Platform SDK

Enterprise AI Agent Infrastructure SDK for building autonomous agent systems.

## Installation

```bash
# Core (minimal)
pip install agenticstar-platform

# With specific modules
pip install agenticstar-platform[db]           # PostgreSQL
pip install agenticstar-platform[rag]          # Qdrant + Embedding
pip install agenticstar-platform[storage]      # Azure Blob, S3, GCS
pip install agenticstar-platform[storage-azure] # Azure Blob only
pip install agenticstar-platform[memory]       # Semantic memory (Mem0)
pip install agenticstar-platform[security]     # PII detection
pip install agenticstar-platform[all]          # All modules
```

## Quick Start

```python
from agenticstar_platform import (
    # Database
    PostgreSQLManager, ApiPostgreSQLManager, PostgreSQLConfig, DataAccess,
    # RAG (Vector DB + Embedding)
    QdrantManager, QdrantConfig, EmbeddingGenerator, EmbeddingConfig,
    # Storage
    AzureBlobStorageClient, AzureBlobConfig,
    # Events
    EventEmitter, EventType,
    # Auth
    AgenticStarAuthClient, AgenticStarAuthConfig,
    # Memory
    SemanticMemoryClient, SemanticMemoryConfig,
)

# Example: Initialize SDK components
async def main():
    # Database (direct connection)
    db_config = PostgreSQLConfig.from_toml("config.toml", section="database")
    manager = PostgreSQLManager(db_config)
    da = DataAccess(manager)
    await da.initialize()
    users = await da.fetch_all("SELECT * FROM users WHERE active = $1", (True,))

    # Database (HTTP API)
    db_config = PostgreSQLConfig(api_url="https://your-api.example.com/db")
    manager = ApiPostgreSQLManager(db_config, token_provider=lambda: "your-token")
    da = DataAccess(manager)
    users = await da.fetch_all("SELECT * FROM users WHERE active = $1", (True,))

    # RAG System
    embedding_config = EmbeddingConfig.from_toml("config.toml", section="rag.embedding")
    embedding_gen = EmbeddingGenerator(embedding_config)

    qdrant_config = QdrantConfig.from_toml("config.toml", section="rag.qdrant")
    async with QdrantManager(qdrant_config, embedding_gen) as qdrant:
        results = await qdrant.search("How to use the SDK?", limit=5)

    # Storage (uses from_dict, not from_toml)
    storage_config = AzureBlobConfig.from_dict({
        "bucket_name": "your-container",
        "connection_string": "your-connection-string",
    })
    storage = AzureBlobStorageClient(storage_config)
```

## Modules

| Module | Extra | Description |
|--------|-------|-------------|
| **db** | `[db]` | PostgreSQL data access layer with Azure AD support |
| **rag** | `[rag]` | Qdrant vector database and Azure OpenAI embedding integration |
| **storage** | `[storage]` / `[storage-azure]` / `[storage-aws]` / `[storage-gcp]` | Multi-cloud storage (Azure Blob, S3, GCS) |
| **auth** | *(core)* | AgenticStar Auth API client (authentication, user management, MCP tokens) |
| **memory** | `[memory]` | Semantic memory (Mem0 + Qdrant) |
| **security** | `[security]` | PII detection (Azure Presidio, AWS Comprehend, GCP DLP) |
| **events** | *(core)* | Event type definitions for streaming |
| **common** | *(core)* | Shared utilities (secret masking, validation) |

### Auth Module

```python
from agenticstar_platform.auth import AgenticStarAuthClient, AgenticStarAuthConfig

# From config.toml [auth.agenticstar] section
config = AgenticStarAuthConfig.from_config("config.toml")
client = AgenticStarAuthClient(config)

# Get user info
user = await client.get_user(user_id="user-001")

# Get MCP tokens
tokens = await client.get_mcp_tokens(user_id="user-001")
```

### Memory Module

Semantic memory powered by Mem0 + Qdrant (requires `pip install agenticstar-platform[memory]`):

```python
from agenticstar_platform.memory import SemanticMemoryClient, SemanticMemoryConfig

config = SemanticMemoryConfig.from_toml("config.toml")
memory = SemanticMemoryClient(config)

# Add memory
await memory.add("User prefers dark mode", user_id="user-001")

# Search memory
results = await memory.search("user preferences", user_id="user-001")
```

### Storage Module

Note: `AzureBlobConfig` uses `from_dict()` (not `from_toml()`):

```python
from agenticstar_platform.storage import AzureBlobStorageClient, AzureBlobConfig

config = AzureBlobConfig.from_dict({
    "bucket_name": "your-container",
    "connection_string": "DefaultEndpointsProtocol=https;...",
    "prefix": "uploads/",
})
client = AzureBlobStorageClient(config)
result = await client.upload_file("local/file.pdf", prefix="docs/")
```

### Telemetry / LLM Usage Tracking (Marketplace)

`TelemetryAccess` (under `db` module) writes records to the `ai_telemetry` table. **Unknown fields are stored in the `metadata` jsonb column automatically** — no schema migration is required to add new tracking dimensions.

For Marketplace agents that wrap LLM calls, the SDK defines **recommended field names** for token and model usage. Following this convention enables cross-agent cost / utilization analytics in shared dashboards.

```python
from agenticstar_platform.db import TelemetryAccess

telemetry = TelemetryAccess(data_access)

# After an LLM call from your custom agent:
response = await openai_client.chat.completions.create(...)

await telemetry.save_telemetry({
    "conversation_id": conversation_id,
    "agent_type": "my_marketplace_agent",
    "service": "my-agent-service",
    "operation": "generate_response",
    "duration_ms": elapsed_ms,
    "success": True,

    # Recommended convention fields (stored automatically in metadata jsonb)
    "prompt_tokens": response.usage.prompt_tokens,
    "completion_tokens": response.usage.completion_tokens,
    "total_tokens": response.usage.total_tokens,
    "model": "azure/gpt-4.1",  # LiteLLM-style identifier
})
```

#### Recommended convention fields

| Field | Type | Source | Notes |
|---|---|---|---|
| `prompt_tokens` | int | `usage.prompt_tokens` (OpenAI / LiteLLM compatible) | Input tokens |
| `completion_tokens` | int | `usage.completion_tokens` | Output tokens |
| `total_tokens` | int | `usage.total_tokens` | Sum |
| `model` | str | LiteLLM-style: `azure/gpt-4.1`, `bedrock/anthropic.claude-3-5-sonnet`, `openai/gpt-4o`, etc. | Provider/model identifier |

These fields are **not** known columns — they land in `metadata` jsonb automatically. No SDK code change, no DB schema migration. Use the recommended names so that your data joins with platform-level analytics.

#### Cross-agent analytics example

```sql
-- Per-model token usage in the last 30 days
SELECT
  metadata->>'model' AS model,
  agent_type,
  SUM((metadata->>'prompt_tokens')::int)     AS total_prompt_tokens,
  SUM((metadata->>'completion_tokens')::int) AS total_completion_tokens,
  COUNT(*)                                    AS invocations,
  AVG(duration_ms)::int                       AS avg_duration_ms
FROM ai_telemetry
WHERE timestamp > NOW() - INTERVAL '30 days'
  AND metadata ? 'prompt_tokens'
GROUP BY model, agent_type
ORDER BY total_prompt_tokens DESC;
```

Pricing / cost conversion is intentionally **out of scope for the SDK** — apply your own model price table downstream (it changes too frequently to embed). The SDK just makes sure tokens and model names are captured consistently.

## Platform Class Example

Below is an example of a Platform class that wraps SDK components for your agent system:

```python
"""
Platform class example - Using AGENTICSTAR Platform SDK
"""
import asyncio
from dataclasses import dataclass
from typing import Optional

from agenticstar_platform import (
    PostgreSQLManager, PostgreSQLConfig, DataAccess,
    QdrantManager, QdrantConfig,
    EmbeddingGenerator, EmbeddingConfig,
    EventEmitter, EventType,
    SemanticMemoryClient, SemanticMemoryConfig,
    AzureBlobStorageClient, AzureBlobConfig,
    AgenticStarAuthClient, AgenticStarAuthConfig,
)


@dataclass
class PlatformConfig:
    """Platform configuration"""
    db_config: PostgreSQLConfig
    qdrant_config: QdrantConfig
    embedding_config: EmbeddingConfig
    storage_config: Optional[AzureBlobConfig] = None
    memory_config: Optional[SemanticMemoryConfig] = None
    auth_config: Optional[AgenticStarAuthConfig] = None

    @classmethod
    def from_toml(cls, path: str) -> "PlatformConfig":
        """Load all configurations from TOML file"""
        return cls(
            db_config=PostgreSQLConfig.from_toml(path, section="database"),
            qdrant_config=QdrantConfig.from_toml(path, section="rag.qdrant"),
            embedding_config=EmbeddingConfig.from_toml(path, section="rag.embedding"),
            storage_config=AzureBlobConfig.from_dict({
                # Load from environment or config
                "bucket_name": "your-container",
                "connection_string": "your-connection-string",
            }),
            auth_config=AgenticStarAuthConfig.from_config(path),
        )


class AgentPlatform:
    """
    Platform class wrapping SDK components.

    Example:
        >>> config = PlatformConfig.from_toml("config.toml")
        >>> platform = AgentPlatform(config)
        >>> await platform.initialize()
        >>>
        >>> # Use database
        >>> users = await platform.db.fetch_all("SELECT * FROM users")
        >>>
        >>> # Use RAG
        >>> results = await platform.search_knowledge("How to deploy?")
        >>>
        >>> # Clean up
        >>> await platform.cleanup()
    """

    def __init__(self, config: PlatformConfig):
        self.config = config
        self._db: Optional[DataAccess] = None
        self._qdrant: Optional[QdrantManager] = None
        self._embedding: Optional[EmbeddingGenerator] = None
        self._storage: Optional[AzureBlobStorageClient] = None
        self._memory: Optional[SemanticMemoryClient] = None
        self._auth: Optional[AgenticStarAuthClient] = None

    async def initialize(self) -> None:
        """Initialize all SDK components"""
        # Database
        db_manager = PostgreSQLManager(self.config.db_config)
        self._db = DataAccess(db_manager)
        await self._db.initialize()

        # Embedding generator
        self._embedding = EmbeddingGenerator(self.config.embedding_config)

        # Vector DB (RAG)
        self._qdrant = QdrantManager(self.config.qdrant_config, self._embedding)
        await self._qdrant.initialize()

        # Storage (optional)
        if self.config.storage_config:
            self._storage = AzureBlobStorageClient(self.config.storage_config)

        # Memory (optional)
        if self.config.memory_config:
            self._memory = SemanticMemoryClient(self.config.memory_config)

        # Auth (optional)
        if self.config.auth_config:
            self._auth = AgenticStarAuthClient(self.config.auth_config)

    @property
    def db(self) -> DataAccess:
        if not self._db:
            raise RuntimeError("Platform not initialized. Call initialize() first.")
        return self._db

    @property
    def qdrant(self) -> QdrantManager:
        if not self._qdrant:
            raise RuntimeError("Platform not initialized. Call initialize() first.")
        return self._qdrant

    @property
    def storage(self) -> Optional[AzureBlobStorageClient]:
        return self._storage

    @property
    def memory(self) -> Optional[SemanticMemoryClient]:
        return self._memory

    @property
    def auth(self) -> Optional[AgenticStarAuthClient]:
        return self._auth

    async def search_knowledge(self, query: str, limit: int = 10):
        return await self.qdrant.search(query, limit=limit)

    async def cleanup(self) -> None:
        """Clean up all resources"""
        if self._qdrant:
            await self._qdrant.close()
        if self._db:
            await self._db.close()
        if self._storage:
            await self._storage.close()
        if self._memory:
            await self._memory.cleanup()
```

## Configuration (config.toml example)

```toml
[database]
host = "your-postgresql.postgres.database.azure.com"
port = 5432
database = "agenticai"
username = "admin"
password = "your-password"
use_azure_ad = false
pool_min_size = 2
pool_max_size = 10
# api_url = "https://your-api.example.com/db"  # Set for HTTP API mode

[database.azure_ad]
tenant_id = "your-tenant-id"
client_id = "your-client-id"
client_secret = "your-client-secret"

[auth.agenticstar]
base_url = "https://auth.agenticstar.tm.softbank.jp"
api_key = ""
timeout = 30.0
max_retries = 3

[rag.embedding]
api_base = "https://your-openai.openai.azure.com/"
api_key = "your-api-key"
deployment_name = "text-embedding-ada-002"

[rag.qdrant]
url = "http://localhost:6333"
collection_name = "knowledge_base"
vector_size = 1536

[storage.azure]
bucket_name = "your-container"
connection_string = "DefaultEndpointsProtocol=https;..."
prefix = "uploads/"

[memory.llm]
model = "azure/gpt-4"
api_key = "your-api-key"
base_url = "https://your-openai.openai.azure.com/"
api_version = "2024-02-15-preview"

[memory.embedder]
model = "azure/text-embedding-ada-002"
api_key = "your-api-key"
base_url = "https://your-openai.openai.azure.com/"
api_version = "2024-02-15-preview"
```

## API Reference

See [API_REFERENCE.md](./API_REFERENCE.md) for detailed API documentation.

## Changelog

### 0.5.7 (2026-05-10)

- **Security: PII confidence threshold per-call** — `detect_pii()` now accepts an optional `confidence_threshold` parameter on Azure / AWS / GCP clients (and the `SecurityClientProtocol` / `SecurityClientBase`). Passing `None` falls back to the value in `*SecurityConfig.pii_confidence_threshold`. This lets a single long-lived `SecurityClient` instance serve callers that need different thresholds, instead of constructing a new client per request. Backward compatible — existing callers that omit the new argument get the previous behavior.
- **Security: GCP threshold now respects config** — `GCPSecurityClient.detect_pii()` previously hardcoded a `LIKELY` (likelihood ≥ 4) cutoff and ignored `GCPSecurityConfig.pii_confidence_threshold`. It now compares `likelihood / 5.0` against the configured threshold, matching Azure / AWS behavior. With the default `pii_confidence_threshold = 0.7` the effective cutoff stays at likelihood ≥ 4, so most callers see no change. Callers that had set `pii_confidence_threshold` below 0.7 will start seeing additional `POSSIBLE` (likelihood 3) findings.
- **Reuse the client to avoid leaks** — `AzureSecurityClient` (and AWS/GCP equivalents) hold an `httpx.AsyncClient` (TLS context + connection pool) internally. Construct one client per process and call `await client.close()` on shutdown (or use `async with`); creating a new client per request without closing leaks resources.

### 0.5.2 (2026-03-28)

- **Memory: Removed episodic memory (Graphiti/FalkorDB)** — `episodic.py` was unused dead code. SDK now provides semantic memory (Mem0) only.
- **Extras: `[semantic]` / `[episodic]` replaced with `[memory]`** — unified extra for Mem0-based semantic memory.
- **Extras: `[all]` no longer includes `graphiti-core[falkordb]`**.
- **README updated** to reflect episodic memory removal.

### 0.5.0 (2026-03-25)

**Breaking Changes:**
- **DB: `DataAccess` now takes a manager instance** instead of `(config, use_proxy, token_provider)`. Callers create `PostgreSQLManager` or `ApiPostgreSQLManager` and pass it directly.
- **DB: `use_proxy` parameter removed** from `DataAccess`, `create_postgresql_manager()`.
- **DB: `api_proxy_url` renamed to `api_url`** in `PostgreSQLConfig`.
- **DB: `ApiPostgreSQLManager` exported** as public API for HTTP API access.

**Improvements:**
- **DB: `is_initialized()` method** added to both `PostgreSQLManager` and `ApiPostgreSQLManager`.
- **Qdrant: `prefer_grpc` / `check_compatibility`** are now explicit `QdrantConfig` fields (no longer hardcoded based on `auth_token_provider`).
- Error messages no longer reference use-case specific terms (CLI/Desktop mode).

### 0.4.0 (2026-03-21)

- **Security: Prompt Shield documents trimming** - `check_prompt_shield()` now trims each document to 10,000 characters to comply with Azure API limits. Previously, WebFetch results exceeding 10,000 characters were blocked even without violations.
- **Security: PII detection language support** - `detect_pii()` now accepts a `language` parameter (default: `"ja"`) for accurate multi-language PII detection. Previously hardcoded to Japanese.
- **Security: Protocol/ABC updated** - `SecurityClientProtocol` and `SecurityClientBase` updated with `language` parameter in `detect_pii()`.

### 0.3.2

- Storage module: Multi-cloud support (Azure Blob, S3, GCS)
- Auth module: AgenticStar Auth API client
- Memory module: Semantic memory (Mem0)

## Version

0.5.7
