> ## Documentation Index
> Fetch the complete documentation index at: https://docs.duraton.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrading

> Every breaking change to the Duraton SDK, what to rename, and why - newest first.

Duraton ships breaking changes without deprecated aliases: the old spelling stops working in the
release that introduces the new one. This page is the record of every such change, so an upgrade is
a mechanical edit rather than a debugging session.

Versions are assigned at publish time, so entries are dated. Check
`npm dist-tag ls @duraton/sdk` for what `latest` and `next` currently point at.

## 2026-09-24 - `step.ai.infer`, `runs.explain` and retired values are removed

`step.ai.infer` and `runs.explain` had no backend on the hosted service, so both only ever failed.
The Kafka and workflow-delete leftovers go with them.

Removed from `@duraton/sdk` and `@duraton/sdk/client`:

* `ctx.step.ai.infer` and the types `InferOptions`, `InferResult`, `InferMessage`
* `client.runs.explain` and the type `ExplainOptions`
* `"infer"` from `AI_STEP_KINDS`
* `"kafka"` from `EVENT_SOURCES`
* `"kafka_source_create"`, `"kafka_source_update"`, `"kafka_source_delete"`,
  `"kafka_delivery_replay"` and `"workflow_delete"` from `CONTROL_ACTION_KINDS`
* `"per-partition"`, `"per-queue"`, `"per-stream"` from `INGRESS_ORDERINGS`
* `"positional"`, `"per-message"` from `INGRESS_ACK_MODELS`
* `"broker"` from `INGRESS_REDELIVERY_OWNERS`

Removed from the API:

* `POST /runs/{id}/explain` and the `explain_run` MCP tool
* `DELETE /workflows/{app}/{name}`
* `POST /data/purge` and `DELETE /data`

Self-hosted engines:

* the engine refuses to start without `DURATON_OPERATOR_KEY`, and no longer reads
  `DURATON_API_KEY` as a built-in key: issue project keys instead
* the engine refuses to start without `DURATON_DATABASE_URL`; SQLite is gone, Postgres only

**What to do:**

* make the model call from your runner with `step.ai.generate`, which is durable and metered the
  same way
* read `event.source` and `controlAction.action` as `StoredEventSource` and
  `StoredControlActionKind`: rows recorded before the removal still carry the old values
* a `CONTROL_ACTION_KINDS` filter no longer accepts a removed kind

Any import or literal of a removed name fails to compile.

## 2026-09-23 - Kafka sources are removed

Duraton no longer consumes Kafka. The engine's Kafka connector is gone, and so is its client
surface in `@duraton/sdk/client`:

* `client.kafka` - the whole `KafkaApi` namespace
* the types `KafkaApi`, `KafkaSource`, `KafkaSourceInput`, `KafkaSourceMapping`,
  `KafkaSourceDelivery`, `KafkaSourceDeliveryAttempt`, `KafkaSourceDeliveryDetail`,
  `KafkaSourceDeliveriesPage`, `KafkaDeliveryReplayResult`, `KafkaRecordHeader`,
  `KafkaDeliveryOutcome`, `KafkaDeliveryLogMode`, `ListKafkaSourceDeliveriesOptions`
* the constants `KAFKA_DELIVERY_OUTCOMES` and `KAFKA_DELIVERY_LOG_MODES`

**What to do:** send events to Duraton over HTTP instead - an inbound webhook source, or
`client.events.send()` from your own consumer process. Any import of the names above fails to compile.

**What still works:** events and audit rows recorded before the removal still read back with
`"kafka"` and the `kafka_*` values. Those values are no longer part of the typed sets (see
2026-09-24); read them as `StoredEventSource` and `StoredControlActionKind`.

## 2026-09-08 - `defineWorkflow` is now `workflow`

The noun did not change, only the prefix.

```ts theme={null}
// before
import { defineWorkflow } from "@duraton/sdk";

export const ticketCreated = defineWorkflow<{ ticketId: string }>({
  name: "ticket.created",
  handler: async (ctx) => { /* ... */ },
});
```

```ts theme={null}
// after
import { workflow } from "@duraton/sdk";

export const ticketCreated = workflow<{ ticketId: string }>({
  name: "ticket.created",
  handler: async (ctx) => { /* ... */ },
});
```

**What to do:** replace the import specifier and the call. Nothing else changes - the options
object, the type parameter, the returned value and the handler signature are all identical.

`defineWorkflow` still works as a deprecated alias of `workflow`, so existing code keeps compiling.
Your editor marks it as deprecated; switch when convenient.

**Watch for one thing.** If you assigned the result to a variable named `workflow`, that variable
now shadows the import inside its own initializer:

```ts theme={null}
const workflow = workflow({ ... });   // ReferenceError, and TypeScript ts(2448)
```

Rename the variable. Naming it after what it does reads better anyway:

```ts theme={null}
const ticketCreated = workflow({ ... });
```

**What is unaffected:** `WorkflowDefinition` and `AnyWorkflowDefinition` keep their names, the
`workflow` field on events and runs is unchanged, and nothing on the wire or in the API moved. A
runner built against the new SDK talks to an unchanged engine.

**Why:** every other authoring function in the SDK is already a bare verb or noun - `connect`,
`agent`, `tool` - and `defineWorkflow` was the only `define*` symbol left.
Across 20 durable-execution and agent frameworks surveyed, none prefixes its authoring function
with `define`; Trigger.dev made the same move from `defineJob` to `task()`.
