---
title: "Build Python agents with routing, retries, and task IDs"
description: "Provides Duale AI's Python SDK runtime for durable AI agents with routing policy, retries, deadlines, typed results, task IDs, and production event tracking for platform engineers."
lang: en
lastUpdated: 2026-06-07
url: https://duale.ai/en/solutions/developers
---

## AI-generated summary

covers SDK capabilities (routing policies, deadlines, typed results, task IDs), the managed runtime handling provider routing, retries and logging, production traits (stable I/O, project controls, provider flexibility), the current Python‑only coverage, plus onboarding and failure‑handling guidance.

- The Python SDK lets developers submit bounded tasks with a routing policy, deadline, typed result model and receive a persistent task ID.
- Duale AI’s managed runtime enforces the routing policy, handles provider selection, retries, deadlines and records task events for integration capture.
- Production-layer features include stable input/output definitions, project-level controls, flexible provider choice, traceable task context, and security‑review support.
- The platform currently supports only Python agents; it does not provide no‑code builders, visual editors, or prebuilt assistant marketplaces.
- Developers request SDK access, install the duale package, set environment variables, persist response.task_id, and handle errors using RFC‑9457 details with retry flags.

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://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

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://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://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

- [Production runtime for durable AI agents](https://duale.ai/en/home.md)
- [Role-based solutions for platform, business, and governance](https://duale.ai/en/solutions.md)
- [Turn AI pilots into a production portfolio](https://duale.ai/en/solutions/business.md)
- [Pricing for reliable AI agent orchestration runtime](https://duale.ai/en/product/pricing.md)
- [Govern AI agents in production with shared operating signals](https://duale.ai/en/solutions/governance.md)
- [Security Trust Center for production AI agents](https://duale.ai/en/product/security.md)

---

## Sitemap

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