Skip to main content

Chucky Client

The main client class for interacting with Chucky in Python.

Installation

pip install chucky-sdk
Or with Poetry:
poetry add chucky-sdk

Import

from chucky import Chucky

Constructor

client = Chucky(
    token: str,
    url: str = 'wss://conjure.chucky.cloud/ws',
    model: str = 'claude-sonnet-4-5-20250929',
    system_prompt: Optional[str] = None,
    max_turns: Optional[int] = None,
    timeout: float = 30.0,
    keepalive_interval: float = 60.0,
)

Parameters

ParameterTypeRequiredDefaultDescription
tokenstrYes-JWT authentication token
urlstrNo'wss://conjure.chucky.cloud/ws'WebSocket server URL
modelstrNo'claude-sonnet-4-5-20250929'Claude model to use
system_promptstrNoNoneSystem prompt
max_turnsintNoNoneMax conversation turns
timeoutfloatNo30.0Connection timeout (seconds)
keepalive_intervalfloatNo60.0Keep-alive interval (seconds)

Example

from chucky import Chucky

client = Chucky(
    token='your-jwt-token',
    model='claude-sonnet-4-5-20250929',
    system_prompt='You are a helpful assistant.',
    timeout=60.0,
)

Methods

prompt()

Send a one-shot prompt and get the response.
async def prompt(
    message: str,
    *,
    model: Optional[str] = None,
    system_prompt: Optional[str] = None,
    tools: Optional[List[Tool]] = None,
    max_turns: Optional[int] = None,
) -> PromptResult

Parameters

ParameterTypeDescription
messagestrThe prompt message
modelstrOverride default model
system_promptstrOverride default system prompt
toolsList[Tool]Tools available to Claude
max_turnsintMax conversation turns

Returns

PromptResult with the response.

Example

result = await client.prompt('What is the capital of France?')
print(result.result)  # "The capital of France is Paris."
print(result.total_cost_usd)  # 0.0012

stream()

Send a prompt with streaming response.
async def stream(
    message: str,
    *,
    model: Optional[str] = None,
    system_prompt: Optional[str] = None,
    tools: Optional[List[Tool]] = None,
    max_turns: Optional[int] = None,
) -> AsyncGenerator[StreamEvent, None]

Example

async for event in client.stream('Write a poem about coding'):
    if event.type == 'message':
        print(event.data, end='', flush=True)
    elif event.type == 'tool_use':
        print(f'\n[Using tool: {event.name}]')

create_session()

Create a new conversation session.
async def create_session(
    *,
    model: Optional[str] = None,
    system_prompt: Optional[str] = None,
    tools: Optional[List[Tool]] = None,
    mcp_servers: Optional[Dict[str, McpServer]] = None,
    max_turns: Optional[int] = None,
) -> Session

Example

session = await client.create_session(
    model='claude-sonnet-4-5-20250929',
    system_prompt='You are a math tutor.',
)

result = await session.send('What is calculus?')
print(result.result)

session()

Context manager for sessions (recommended).
def session(
    *,
    model: Optional[str] = None,
    system_prompt: Optional[str] = None,
    tools: Optional[List[Tool]] = None,
    mcp_servers: Optional[Dict[str, McpServer]] = None,
) -> AsyncContextManager[Session]

Example

async with client.session(system_prompt='You are helpful.') as session:
    r1 = await session.send('Hi, I am Alice')
    r2 = await session.send('What is my name?')
    print(r2.result)  # "Your name is Alice."
# Session automatically closed

close()

Close the client and release resources.
async def close() -> None

Example

await client.close()

Session Class

Methods

send()

Send a message and wait for response.
async def send(message: str) -> SessionResult

stream()

Send a message with streaming.
async def stream(message: str) -> AsyncGenerator[StreamEvent, None]

close()

Close the session.
async def close() -> None

Properties

session_id

The session’s unique identifier.
@property
def session_id(self) -> Optional[str]

Result Types

PromptResult

@dataclass
class PromptResult:
    result: str                      # Response text
    total_cost_usd: Optional[float]  # Total cost in USD
    duration_secs: Optional[float]   # Response time
    session_id: Optional[str]        # Session ID (if applicable)

SessionResult

@dataclass
class SessionResult:
    result: str
    total_cost_usd: Optional[float]
    duration_secs: Optional[float]
    turn_count: Optional[int]
    session_id: Optional[str]

StreamEvent

@dataclass
class StreamEvent:
    type: str       # 'message', 'tool_use', 'tool_result', 'error'
    data: Any       # Event-specific data
    name: Optional[str]  # Tool name (for tool_use)

Complete Example

import asyncio
from chucky import Chucky, tool, text_result

# Define a tool
@tool('get_time', 'Get current time')
async def get_time() -> ToolResult:
    from datetime import datetime
    return text_result(datetime.now().isoformat())

async def main():
    # Create client
    client = Chucky(
        token='your-jwt-token',
        model='claude-sonnet-4-5-20250929',
    )

    try:
        # Simple prompt
        result = await client.prompt('What is 2 + 2?')
        print(f'Answer: {result.result}')
        print(f'Cost: ${result.total_cost_usd:.4f}')

        # Streaming
        print('\nStreaming response:')
        async for event in client.stream('Tell me a joke'):
            if event.type == 'message':
                print(event.data, end='')
        print()

        # Session with tools
        async with client.session(tools=[get_time]) as session:
            r = await session.send('What time is it?')
            print(f'\nTime response: {r.result}')

    finally:
        await client.close()

asyncio.run(main())

Error Handling

from chucky import Chucky, BudgetExceededError, AuthenticationError

client = Chucky(token='...')

try:
    result = await client.prompt('Hello')
except BudgetExceededError as e:
    print(f'Budget exceeded: {e}')
except AuthenticationError as e:
    print(f'Auth failed: {e}')
except Exception as e:
    print(f'Error: {e}')