---
title: "Use Python SDK for stable contracts, routing, and retries"
description: "Provide a Python SDK enabling platform teams to build durable AI agents with contracts, routing policy, retries, deadlines, typed results, task IDs and secure review context."
lang: en
lastUpdated: 2026-06-07
url: https://dev.duale.ai/en/solutions/developers
---

## AI-generated summary

The page describes Duale AI’s Python‑first runtime for platform engineers, showing how the SDK lets developers submit bounded agent tasks with routing policies, deadlines, retries and typed results, and how task events and context are captured. It notes support is limited to Python.

- The Python SDK lets you submit bounded agent tasks, specify a routing policy, set a deadline, and request a typed result model.
- Provider routing treats models as replaceable capacity; the runtime scores models against the policy and selects one per task.
- Task events include submission, routing decisions, retries, terminal results, errors, and are exposed via the SDK event stream.
- The runtime enforces retries and deadlines, keeping those behaviors explicit instead of embedding them in application code.
- Current coverage is limited to Python; the product does not provide SDKs for other languages, visual or no‑code builder tools, or a pre‑built assistant marketplace.

Summaries were generated by AI. Generative AI is experimental.

---

<Hero
  eyebrow="For platform leads"
  title={
<>
  Build Python agents your platform team can <AccentText>operate</AccentText>
</>
}
  subtitle="Duale AI gives Python teams a durable runtime for bounded agent work: stable contracts, routing policy, retries, task identifiers, and project-specific review context without tying every project to one provider stack."
  primaryCta={{ label: "Request Python access", dialog: "contact" }}
  secondaryCta={{ label: "See pricing", href: "https://dev.duale.ai/en/product/pricing.md" }}
/>

<Section title="Supported today" subtitle="The developer promise is intentionally narrow: Python first, runtime primitives first, production path first.">
  <CardGrid columns={3}>
    <Card title="Python SDK" icon="code">
      Use Python to submit bounded agent work, attach routing policy, set deadlines, request typed results, and keep a
      task identifier for follow-up.
    </Card>

    <Card title="Provider routing" icon="mixer-horizontal">
      Treat models as replaceable capacity. Route by policy inputs such as quality, speed, guardrail preference, and
      priority instead of hard-coding every call.
    </Card>

    <Card title="Task events" icon="commit">
      Task submission, terminal result, timeouts, errors, retries, and routing decisions can become product events where
      the integration captures them.
    </Card>
  </CardGrid>
</Section>

<Band>
  <Section title="Python shape" subtitle="Real code path, not a multi-framework marketing grid.">
    ```python
    import asyncio
    from datetime import datetime, timedelta, timezone

    from pydantic import BaseModel

    from duale import DualeConfig, DualeSDK, RoutingPolicy, ask

    class SupportDecision(BaseModel):
        next_action: str
        reason: str
        risk: str

    async def main() -> None:
        deadline = datetime.now(timezone.utc) + timedelta(minutes=30)

        async with DualeSDK(config=DualeConfig(), auto_start=False) as sdk:
            response = await ask(
                action="Review this support case and return the next safe action.",
                res=SupportDecision,
                routing=RoutingPolicy(
                    target_accuracy=0.8,
                    target_guardrails=0.7,
                    speed_preference=0.4,
                ),
                deadline=deadline,
                sdk=sdk,
            )
            decision = await response.model()
            print(response.task_id, decision.next_action)

    asyncio.run(main())
    ```
  </Section>
</Band>

<Section title="Reusable production layer" subtitle="The point is to stop every agent project from inventing its own production substrate.">
  <CardGrid columns={3}>
    <Card title="Retries and deadlines" icon="exclamation-triangle">
      Agent work can fail, run long, or need a safer route. The runtime keeps those behaviors explicit instead of hiding
      them in application glue.
    </Card>

    <Card title="Stable input and output" icon="file-text">
      Define the work boundary once. Models, provider policy, retention, and governance requirements can change without
      rewriting the business algorithm.
    </Card>

    <Card title="Project controls" icon="eye">
      Keep enough task context for teams to decide whether a workflow should continue, retry, pause, or move to a
      project-specific review step. The product does not make that review policy implicit.
    </Card>

    <Card title="Provider choices" icon="layers">
      Move between supported model providers as costs, latency, quality, and requirements change. The agent contract
      remains the durable interface.
    </Card>

    <Card title="Traceable task context" icon="reader">
      Keep enough context to understand why a task succeeded, failed, waited, or retried where the integration records
      those signals.
    </Card>

    <Card title="Security review" icon="lock-closed" href="https://dev.duale.ai/en/product/security.md">
      Security teams can review hosting, subprocessors, access controls, data movement, and requestable review inputs
      before a project expands.
    </Card>
  </CardGrid>
</Section>

<Section title="What happens after task submission" subtitle="One task submission becomes a bounded runtime task. Your policy stays explicit, provider choice stays configurable where supported, and the task identifier plus typed result return to your code.">
  ```mermaid
  flowchart LR
      %% WHAT: SDK integration view — where your code meets Duale, what stays in Configured, what runs in Managed, what comes back.
      %% WHO: Lead Python developer and platform engineer integrating the Duale AI SDK.
      %% WHY: Make the SDK boundary explicit so the dev sees their own responsibility next to what Duale owns.
      %% NOT: Timeline or sequence diagram, internal service topology, long autonomous loops, or admin interface claims.
      accTitle: Inside Duale AI for Python developers
      accDescr {
        Your Python code submits work with a task, a deadline, a response
        type, and a routing policy. Inside Duale, the Configured zone holds
        the policy your team owns. The Managed zone tracks task state, routes
        work, retries where configured, records events, and returns the
        terminal result. The typed result and task identifier return to your
        code.
      }

      Code(Your code: ask, deadline, policy, response type)
      subgraph Duale[Duale AI platform]
          subgraph Configured[Configured by your team]
              Policy(Routing policy, deadlines, retention expectations)
          end
          subgraph Managed[Managed by Duale]
              Ledger(Task state, routing, retries)
              Final(Events and terminal result)
          end
      end
      ModelProvider(Selected model provider)

      Code <-.-> Duale
      Configured --> Managed
      Duale <--> ModelProvider
  ```
</Section>

<Section title="Fit today" subtitle="Clear boundaries are better than broad claims.">
  <CardGrid columns={2}>
    <Card title="Use Duale AI for" icon="check">
      Python agents that need routing policy, recovery behavior, typed results, task context, and a path from prototype
      to operated software.
    </Card>

    <Card title="Current boundary" icon="exclamation-triangle">
      Other language-native development, visual agent builders, prebuilt assistant marketplaces, or framework-specific
      starter packs.
    </Card>
  </CardGrid>
</Section>

## Developer questions

### How do I get started with the SDK

Request Python access from the contact form. Install the `duale` package, set `DUALE_TENANT_ID` and
`DUALE_AUTH_TOKEN`, instantiate `DualeSDK(config=DualeConfig())`, and submit a first bounded task with
`ask(action=..., res=..., routing=RoutingPolicy(...), deadline=..., sdk=sdk)`. The first agent runs on the
evaluation workspace before any production rollout.

### How does provider routing work from the SDK

Your code submits a `RoutingPolicy` with target accuracy, guardrails, and speed preference. The runtime scores
supported models against the policy and selects one per task; your agent code never calls a model provider directly.
Cross-provider discovery and fallback ordering are roadmap, not shipped today.

### What should my application store after submission

Persist `response.task_id` — that is the durable correlator for everything your application logs about this task. The
terminal result comes back from `await response.model()`, validated against the response model passed to `ask`. On
failure, `DualeError.problem_details` carries the RFC 9457 envelope: `error_code`, `detail`, `retryable`,
`retry_after_seconds`, and `error_category`. Live content deltas and tool-use events arrive on `response.stream()`
while the task runs; if your product needs a retrievable history of those events, store them in your own system as
they stream — the SDK does not expose a replay endpoint today.

### How does the SDK handle retries and failures

The SDK's HTTP transport reconnects dropped event streams with exponential backoff and jitter; the runtime owns
task-level retries within bounded policy. Your code does not implement either layer. Failed tasks return a terminal
failure result with an error category and a `retryable` flag; the task identifier links to the routing decision and
event history for that attempt.

### When is Duale AI not the right fit yet

Duale AI is a runtime, not an agent framework, a model gateway, a model provider, or a managed cloud agent platform.
It is not the right fit if you need a non-Python development path, a no-code agent builder, a visual agent builder,
a prebuilt assistant marketplace, a framework-specific starter pack, or a packaged employee assistant. The supported
surface today is the Python SDK task-submission path: bounded action, routing policy, deadline, typed result, and
task identifier.

<Cta title="Bring one Python agent and test the production path." primaryCta={{ label: "Request Python access", dialog: "contact" }} secondaryCta={{ label: "Review security posture", href: "https://dev.duale.ai/en/product/security.md" }} />

<JsonLd
  data={{
"@type": "SoftwareApplication",
name: "Duale AI",
applicationCategory: "DeveloperApplication",
audience: {
  "@type": "BusinessAudience",
  audienceType: "Platform engineers and Python developers",
},
offers: {
  "@type": "Offer",
  priceCurrency: "EUR",
  availability: "https://schema.org/PreOrder",
},
description:
  "Python-first runtime for durable AI agents with routing policy, retries, typed results, runtime events where configured, and stable contracts.",
operatingSystem: "Web",
}}
/>

## Related content

- [Deploy durable AI agents with stable contracts and routing](https://dev.duale.ai/en/home.md)
- [Role-based solutions for production AI agents](https://dev.duale.ai/en/solutions.md)
- [Turn AI pilots into a production portfolio](https://dev.duale.ai/en/solutions/business.md)
- [Pricing for reliable AI agent orchestration](https://dev.duale.ai/en/product/pricing.md)
- [Govern AI agents with shared operating model for compliance](https://dev.duale.ai/en/solutions/governance.md)
- [Review security posture for production AI agents](https://dev.duale.ai/en/product/security.md)

---

## Sitemap

See the full [Markdown sitemap](https://dev.duale.ai/sitemap.md) for all pages.
