You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Documents the payload codec contract introduced for
zorporation/durable-workflow#164: canonical codec names, how
`POST /api/workflows` accepts plain JSON arrays vs. explicit
`{codec, blob}` envelopes, per-run codec propagation, and the
trade-offs between the `json` codec (portable) and the legacy PHP
codecs (PHP-only but preserves arbitrary PHP values).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: docs/configuration/worker-protocol.md
+61Lines changed: 61 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -145,6 +145,67 @@ The `ActivityTaskBridge` contract defines how an external worker interacts with
145
145
146
146
Activity heartbeat responses include `can_continue` and `cancel_requested` fields, allowing long-running activities to respond to cancellation requests.
147
147
148
+
## Payload Codecs
149
+
150
+
Every payload byte string that crosses the worker-protocol boundary is tagged with a **`payload_codec`** naming the format of the accompanying blob. Codecs are language-neutral so any SDK — PHP, Python, Go, TypeScript, Rust — can encode and decode payloads without sharing a runtime or an HMAC key.
151
+
152
+
### Canonical Codec Names
153
+
154
+
| Codec | Description |
155
+
|-------|-------------|
156
+
|`json`| Raw UTF-8 JSON document (default for new workflows). No wrapping, no signing. Round-trips any JSON-representable value. |
157
+
|`workflow-serializer-y`| PHP `SerializableClosure` with byte-escape encoding. Legacy; requires a shared `config('app.key')` between server and worker. |
158
+
|`workflow-serializer-base64`| PHP `SerializableClosure` with base64 encoding. Legacy. |
159
+
160
+
Legacy fully-qualified PHP class names (e.g. `Workflow\Serializers\Y`) are accepted as aliases so runs persisted before the codec rename keep decoding.
161
+
162
+
### Wire Format: Payload Envelope
163
+
164
+
On fields that carry payload bytes (`arguments`, `result`, `payload`, etc.), the worker protocol surfaces the codec alongside the opaque string. Poll responses look like:
165
+
166
+
```json
167
+
{
168
+
"task_id": "...",
169
+
"payload_codec": "json",
170
+
"arguments": "[\"hello\", 42]",
171
+
"history_events": [ ... ]
172
+
}
173
+
```
174
+
175
+
The worker reads `payload_codec` to choose a decoder. A non-matching codec is a clear error — the worker should not attempt to sniff or guess.
176
+
177
+
### Starting a Workflow
178
+
179
+
`POST /api/workflows` accepts `input` in two shapes:
180
+
181
+
1.**Plain JSON array** — the server JSON-encodes and tags the run with `payload_codec = "json"`.
The server stores the blob verbatim and tags the run with the declared codec.
197
+
198
+
The chosen codec is stored on the `WorkflowRun` and **propagates for the life of the run**: activity arguments, results, signal/update arguments, and child-workflow inputs all use the same codec unless explicitly overridden.
199
+
200
+
### Per-Codec Compatibility
201
+
202
+
-**`json`** — portable across all SDKs. JSON-native types only (no Eloquent models, closures, or arbitrary PHP objects).
203
+
-**`workflow-serializer-y` / `workflow-serializer-base64`** — PHP-only. Supports arbitrary PHP values (including Eloquent models, closures) but cannot be read by non-PHP workers. Use only when server and workers all run the same PHP codebase with a shared app key.
204
+
205
+
### Default Codec
206
+
207
+
The default codec is chosen from `config('workflows.serializer')` for installations that explicitly set it; new deployments default to `json`. Clients that omit `input` on `POST /api/workflows` inherit the default.
208
+
148
209
## Resolving the Bridges
149
210
150
211
Both bridges are registered in the Laravel container and can be resolved directly:
0 commit comments