Skip to content

Latest commit

 

History

History
365 lines (284 loc) · 11.5 KB

File metadata and controls

365 lines (284 loc) · 11.5 KB

SDK STATUS & REPRODUCTION REPORT

Date: January 9, 2026

SUMMARY

  1. Outbound Calls: ✅ WORKING
  2. Analytics (SDK): ❌ FAILED (Validation Error on Voice Enum) -> REST Fallback WORKS
  3. Campaigns: ⚠️ PARTIAL (API works, but Audience creation missing from SDK)
  4. Knowledge Base: ✅ WORKING (Files) / ❌ FAILED (Text Upload)
  5. Core Concepts: 🚨 CRITICAL (Event Handler Registration fails silently)

DETAILED FINDINGS & REPRODUCTION SNIPPETS

  1. ANALYTICS / CALL LOGS

STATUS: FAILED (SDK Validation Error) ISSUE: The API returns model: "waves_lightning_v2", but the SDK Pydantic model (AgentDTOSynthesizerVoiceConfig) restricts values to ['waves', 'waves_lightning_large', 'waves_lightning_large_voice_clone'].

REPRODUCTION CODE:

from smallestai.atoms import AtomsClient
client = AtomsClient()

# Use any valid conversation ID (e.g. from a recent call)
call_id = "CALL-1767975473535-0d7922"

try:
    # This throws Pydantic ValidationError
    logs = client.get_conversation_logs(id=call_id)
    print("Success")
except Exception as e:
    print(f"FAILED: {e}")

ERROR OUTPUT:

1 validation error for AgentDTOSynthesizerVoiceConfig model Value error, must be one of enum values (...) [input_value='waves_lightning_v2', input_type=str]

  1. CAMPAIGNS (AUDIENCE CREATION)

STATUS: BLOCKED (Missing SDK Method & Undocumented REST API) ISSUE:

  1. SDK: No AudiencesApi or create_audience method exposed.
  2. REST API: Attempting to use POST /api/v1/audience (both JSON and Multipart CSV) fails with: {"status":false,"errors":["Failed to create audience. Please check your CSV file and try again."]} The API requires a specific CSV format/upload method that is not documented.

REPRODUCTION CODE (REST Attempt):

import requests
# ... setup headers ...
url = "https://atoms.smallest.ai/api/v1/audience"
# Tried JSON payload -> Failed
# Tried Multipart CSV upload -> Failed
response = requests.post(url, headers=headers, ...)
print(response.json())
  1. CORE CONCEPTS (EVENT HANDLERS)

STATUS: CRITICAL FAILURE (Silent Fail) ISSUE: In AgentSession, the add_event_handler method (used by @on_event decorator) silently drops handlers (with only a warning log) if the event name has not been explicitly pre-registered using _register_event_handler. By default, only on_event_received is registered in __init__. Users following docs (@session.on_event("system.user_joined")) will find their code never runs.

LOCATION: smallestai/atoms/agent/session.py lines 374-385.

REPRODUCTION CODE:

# In any agent test or app
@session.on_event("system.user_joined")
async def welcome(session, event):
    print("This will NEVER run")

# Logs will show: "Event handler system.user_joined not registered"

RECOMMENDED FIX: Modify add_event_handler to auto-register new events:

if event_name in self._event_handlers:
    self._event_handlers[event_name].handlers.append(handler)
else:
    # AUTO-REGISTER instead of warning
    self._register_event_handler(event_name)
    self._event_handlers[event_name].handlers.append(handler)
  1. KNOWLEDGE BASE (TEXT UPLOAD)

STATUS: FAILED (404 Not Found) ISSUE: The upload-text endpoint seems to be missing or invalid.

REPRODUCTION CODE:

from smallestai.atoms import AtomsClient
from smallestai.atoms.models.knowledgebase_id_items_upload_text_post_request import KnowledgebaseIdItemsUploadTextPostRequest

client = AtomsClient()
kb_id = "your-kb-id"

try:
    client.upload_text_to_knowledge_base(
        id=kb_id,
        knowledgebase_id_items_upload_text_post_request=KnowledgebaseIdItemsUploadTextPostRequest(
            text="Menu items...",
            title="Menu"
        )
    )
except Exception as e:
    print(f"FAILED: {e}")

ERROR OUTPUT:

404 Not Found (from API)

  1. AGENT DELETION

STATUS: FAILED (404 Not Found) ISSUE: client.delete_agent() often returns 404 even for valid Agent IDs.

  1. GET ORGANIZATION (RATE LIMITS)

STATUS: FAILED (404 Not Found) ISSUE: The get_organization() method documented in rate-limits.mdx doesn't exist on the backend.

REPRODUCTION CODE:

from smallestai.atoms import AtomsClient
client = AtomsClient()

org = client.get_organization()  # → 404 "Cannot GET /api/v1/organization"

IMPACT: The entire "Rate Limits" documentation page's usage-checking snippets do not work.

  1. CALL CONTROL IMPORTS

STATUS: FAILED (Import Errors) ISSUE: The call-control.mdx documentation uses imports that do not exist in the SDK:

DOCUMENTED (Wrong):

from smallestai.atoms import SDKAgentEndCallEvent
from smallestai.atoms import SDKAgentTransferConversationEvent
from smallestai.atoms.agentic import OutputAgentNode
from smallestai.atoms.agentic.tools import function_tool

ACTUAL LOCATION:

  • SDKAgentEndCallEvent and SDKAgentTransferConversationEvent are in smallestai.atoms.agent.events
  • OutputAgentNode is in smallestai.atoms.agent.nodes.output_agent
  • There is NO smallestai.atoms.agentic module

IMPACT: All call-control.mdx code snippets fail with ImportError.

  1. CAMPAIGN SDK MISSING FIELDS

STATUS: PARTIAL (SDK limited, REST works) ISSUE: The SDK CampaignPostRequest model only supports 4 fields, but the API accepts more.

SDK FIELDS (4):

  • name
  • description
  • agentId
  • audienceId

API FIELDS (missing from SDK):

  • maxRetries (int, 0-10) - retry attempts for unanswered calls
  • retryDelay (int, 1-1440) - minutes between retries
  • scheduledAt (ISO string) - auto-start time

REPRODUCTION CODE:

from smallestai.atoms import AtomsClient
client = AtomsClient()

# These extra fields are IGNORED by SDK
campaign = client.create_campaign(
    campaign_post_request={
        "name": "Test",
        "agentId": "agent-id",
        "audienceId": "audience-id",
        "maxRetries": 5,    # Ignored! Defaults to 3
        "retryDelay": 30    # Ignored! Defaults to 15
    }
)

WORKAROUND: Use REST API directly for full functionality:

import requests
response = requests.post(
    "https://atoms.smallest.ai/api/v1/campaign",
    headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
    json={
        "name": "Test",
        "agentId": "agent-id",
        "audienceId": "audience-id",
        "maxRetries": 5,        # Works!
        "retryDelay": 30,       # Works!
        "scheduledAt": "..."    # Works!
    }
)

IMPACT: Users cannot configure retry settings or scheduling via SDK.

  1. CAMPAIGN get_campaign_by_id PARSING

STATUS: PARTIAL (API works, SDK parsing broken) ISSUE: get_campaign_by_id() returns a Pydantic object with all fields as None, even though the API returns valid data.

REPRODUCTION CODE:

status = client.get_campaign_by_id(id=campaign_id)
print(status.data)
# Output: id=None name=None description=None ... (all None)

WORKAROUND: Use REST API:

response = requests.get(f"https://atoms.smallest.ai/api/v1/campaign/{campaign_id}", headers=headers)
data = response.json()["data"]["campaign"]
print(data["status"])  # Works!

IMPACT: SDK users cannot reliably check campaign status.

  1. AGENT telephonyProductId NOT WORKING

STATUS: FAILED (Field ignored) ISSUE: The telephonyProductId field exists in the API spec for creating agents, but passing it doesn't actually link the phone to the agent.

REPRODUCTION CODE:

import requests

response = requests.post(
    "https://atoms.smallest.ai/api/v1/agent",
    headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
    json={
        "name": "Test Agent",
        "telephonyProductId": ["phone-product-id"]  # Must be array
    }
)
# Returns 201 success, but phone is NOT linked to agent

# Verify - phoneNumber field is empty:
agent = requests.get(f"https://atoms.smallest.ai/api/v1/agent/{agent_id}", ...)
print(agent.json()["data"]["phoneNumber"])  # Returns []

# Campaign fails:
# "No phone numbers available for campaign"

EXPECTED: Phone should be linked to agent when passed during creation. ACTUAL: Phone is not linked. Campaign requires phone but fails.

WORKAROUND: Link phone to agent via Dashboard UI only (no API available).

IMPACT: Cannot programmatically set up agents with phone numbers for campaigns.

  1. SDK SERVER SESSION DISCONNECT

STATUS: BUG (Session closes immediately) ISSUE: When running AtomsApp server, sessions disconnect immediately after setup_handler completes.

ROOT CAUSE: The server.py create_session() method calls session.initialize() but the session only stays alive when setup_handler calls both session.start() AND session.wait_until_complete().

REPRODUCTION CODE:

# This FAILS - session closes immediately
async def setup_session(session: AgentSession):
    agent = MyAgent()
    session.add_node(agent)
    # Missing start() and wait_until_complete()!

# This WORKS - session stays alive  
async def setup_session(session: AgentSession):
    agent = MyAgent()
    session.add_node(agent)
    await session.start()
    await session.wait_until_complete()

FIX: Document that setup_handler MUST call session.start() and session.wait_until_complete().

  1. CLI CHAT 'async for' ERROR

STATUS: BUG (Internal SDK Error) ISSUE: When using smallestai agent chat to connect to an AtomsApp server, sending messages causes:

Error: 'async for' requires an object with aiter method, got coroutine

REPRODUCTION:

# Terminal 1:
python server.py

# Terminal 2:
smallestai agent chat
# Type a message → Error appears

IMPACT: Cannot use CLI chat client to test agents locally in some configurations.

  1. CAMPAIGNS COMPLETE STATUS

STATUS: BLOCKED (Multiple Issues)

Issues Found:

  1. SDK create_campaign missing fields: maxRetries, retryDelay, scheduledAt only available via REST API, not SDK.

  2. get_campaign_by_id() parsing error: Returns None for all fields. Must use REST API to check campaign status.

  3. pause_campaign() 500 Error: Backend returns 500 Internal Server Error on pause.

  4. No programmatic phone linking: telephonyProductId field is ignored. Phones must be linked to agents via Dashboard UI.

  5. Audience creation undocumented: No SDK method to create audience. REST API returns cryptic CSV error.

WORKAROUND (Full Campaign Lifecycle):

# 1. Create agent in Dashboard with phone linked

# 2. Create audience via Dashboard

# 3. Create campaign via REST API (for full control):
response = requests.post(
    "https://atoms.smallest.ai/api/v1/campaign",
    headers={"Authorization": f"Bearer {API_KEY}"},
    json={
        "name": "My Campaign",
        "agentId": "agent-id",
        "audienceId": "audience-id",
        "maxRetries": 3,
        "retryDelay": 60,
        "scheduledAt": "2026-01-15T10:00:00Z"
    }
)

# 4. Start campaign:
requests.post(f"https://atoms.smallest.ai/api/v1/campaign/{campaign_id}/start", ...)

# 5. Check status via REST (SDK parsing broken):
response = requests.get(f"https://atoms.smallest.ai/api/v1/campaign/{campaign_id}", ...)
status = response.json()["data"]["campaign"]["status"]

IMPACT: Campaign setup requires Dashboard + REST API combination. SDK alone insufficient.