Dedalus Python Library

repository·main·Indexed 20 days ago

https://github.com/dedalus-labs/dedalus-agents-python

The official Python library for the Dedalus API, providing a high-level, type-safe interface for interacting with the Dedalus REST API. It supports synchronous and asynchronous workflows (including an optional aiohttp backend), SSE streaming, and Pydantic-based response models. The library enables access to AI models, text embeddings, audio capabilities (speech, transcription, and translation), and image generation and editing.

Tokens
14.2K
Snippets
42
Records
66
Agent score
68%

What's inside dedalus_labs

  1. Differentiate between null and missing fields

    main

    In API responses, a field that is explicitly null or missing entirely will both result in None in Python. To distinguish them, check the .model_fields_set attribute on the response object.

    if response.my_field is None:
      if 'my_field' not in response.model_fields_set:
        print('Field was missing from JSON')
      else:
        print('Field was explicitly null in JSON')
  2. Understand Dedalus types and models

    main

    The library uses standard Python typing to provide a robust developer experience:

    • Request Parameters: Nested parameters are defined using TypedDict. This allows you to pass dictionaries that match specific structures (e.g., audio={'format': 'wav', 'voice': 'string'}).
    • Response Fields: Responses are returned as Pydantic models. These models include helper methods:
      • model.to_json(): Serializes the model back into a JSON string.
      • model.to_dict(): Converts the model into a standard Python dictionary.

    To enable type checking in VS Code, set python.analysis.typeCheckingMode to basic.

  3. Enable aiohttp backend for AsyncDedalus

    main

    By default, the async client uses httpx. For improved concurrency performance, you can use aiohttp as the HTTP backend.

    1. Install the extra dependency:
    pip install dedalus_labs[aiohttp]
    1. Instantiate the client with http_client=DefaultAioHttpClient().
    import os
    import asyncio
    from dedalus_labs import DefaultAioHttpClient
    from dedalus_labs import AsyncDedalus
    
    
    async def main() -> None:
        async with AsyncDedalus(
            api_key=os.environ.get("DEDALUS_API_KEY"),  # This is the default and can be omitted
            http_client=DefaultAioHttpClient(),
        ) as client:
            chat_completion = await client.chat.completions.create(
                model="openai/gpt-5-nano",
                messages=[
                    {
                        "role": "system",
                        "content": "You are Stephen Dedalus. Respond in morose Joycean malaise.",
                    },
                    {
                        "role": "user",
                        "content": "Hello, how are you today?",
                    },
                ],
            )
            print(chat_completion.id)
    
    
    asyncio.run(main())
  4. Handle Dedalus API errors

    main

    All errors in the library inherit from dedalus_labs.APIError.

    • Connection Errors: If the library cannot connect to the API (network issues, timeouts), it raises a subclass of dedalus_labs.APIConnectionError.
    • Status Errors: If the API returns a non-success status code (4xx or 5xx), it raises a subclass of dedalus_labs.APIStatusError. These objects contain status_code and response properties.
    • Timeouts: If a request times out, an APITimeoutError is thrown.
    import dedalus_labs
    from dedalus_labs import Dedalus
    
    client = Dedalus()
    
    try:
        client.chat.completions.create(
            model="openai/gpt-5-nano",
            messages=[{"role": "user", "content": "Hello"}],
        )
    except dedalus_labs.APIConnectionError as e:
        print("The server could not be reached")
    except dedalus_labs.RateLimitError as e:
        print("A 429 status code was received; we should back off a bit.")
    except dedalus_labs.APIStatusError as e:
        print(f"Status: {e.status_code}")
  5. Manage HTTP resources and client lifecycle

    main

    The library closes connections when the client is garbage collected. However, it is best practice to manually close the client using the .close() method or by using the client as a context manager.

    from dedalus_labs import Dedalus
    
    with Dedalus() as client:
        # make requests here
        ...
    # HTTP client is now closed
  6. Understand the structure of CreateTranslationResponse

    main

    The TranslationCreateResponse is a union type that can return either a simplified JSON response or a verbose JSON response containing detailed segment information.

    • CreateTranslationResponseJSON: A minimal response containing only the text field.
    • CreateTranslationResponseVerboseJSON: A detailed response containing the full text, the language (always english), the total duration of the input audio, and an optional list of segments providing granular timing and metadata for the translation.
  7. Configure default headers

    main

    The SDK automatically sends User-Agent: Dedalus-SDK and X-SDK-Version: 1.0.0. You can override these by passing a default_headers dictionary to the Dedalus client constructor.

    from dedalus_labs import Dedalus
    
    client = Dedalus(
        default_headers={"User-Agent": "My-Custom-Value"},
    )
  8. Understand the ChatCompletion response structure

    main

    The ChatCompletion object is an OpenAI-compatible response extended with Dedalus-specific features for server-side tool execution tracking, MCP (Model Context Protocol) error reporting, and session management.

    Key Dedalus extensions include:

    • correlation_id: A stable session ID used for cross-turn handoff. Echo this ID in your next request to resume server-side execution state.
    • pending_tools: A list of PendingTool objects representing tool calls that the client must execute. These include id, name, arguments, and an optional dependencies list for ordering.
    • mcp_server_errors: A dictionary of MCPServerErrors keyed by server name, providing error messages, codes, and recommendations for MCP server failures.
    • mcp_tool_results: Detailed execution logs (inputs, outputs, timing) for MCP tools.
    • server_results: Outputs from completed server-side tools, keyed by call ID.
    • service_tier: Indicates the processing mode used (e.g., auto, default, flex, scale, priority).
    • turns_consumed: The number of internal LLM calls made during the request.
    • tools_executed: A list of names of tools that were executed entirely on the server.
  9. Understand transcription response formats

    main

    When performing transcription tasks, the API returns one of two primary response structures, which can be unified under the TranscriptionCreateResponse type alias:

    1. CreateTranscriptionResponseJSON (Standard): A lightweight response containing the transcribed text, optional logprobs (for specific models like gpt-4o-transcribe), and usage statistics.
    2. CreateTranscriptionResponseVerboseJSON (Verbose): A detailed response containing the full text, language, duration, and optional granular breakdowns including words (with timestamps), segments (with metadata like avg_logprob and no_speech_prob), and usage statistics.

    Use the verbose response when you need precise timing for words or segments, or when you need to analyze the quality of the transcription via logprobs and compression ratios.

    from typing import Union
    from dedalus_labs.types.audio.transcription_create_response import TranscriptionCreateResponse
    
    # TranscriptionCreateResponse will be either a Verbose or Standard JSON response
    response: TranscriptionCreateResponse = await client.audio.transcriptions.create(...)
  10. Configure retries and timeouts

    main

    Retries

    Certain errors (Connection errors, 408 Request Timeout, 409 Conflict, 429 Rate Limit, and >=500 Internal errors) are automatically retried 2 times by default with exponential backoff. Use max_retries to change this.

    Timeouts

    Requests timeout after 1 minute by default. You can provide a float (seconds) or an httpx.Timeout object. Note that timed-out requests are also retried twice by default.

    Use max_retries and timeout either when initializing the Dedalus client or per-request using .with_options().

    from dedalus_labs import Dedalus
    import httpx
    
    # Configure defaults for the client
    client = Dedalus(
        max_retries=0,
        timeout=20.0
    )
    
    # Or configure per-request
    client.with_options(max_retries=5, timeout=5.0).chat.completions.create(
        model="openai/gpt-5-nano",
        messages=[{"role": "user", "content": "Hello"}],
    )