---
title: "Data shapes · Agent Wranglers"
url: https://agentwranglers.se/playbook/architecture/data-shapes
updated: 2026-10-20
licence: "All rights reserved"
---

# Data shapes

By Erik Bergstedt, Agent Wranglers. Updated 2026-10-20.

> Pass data as named, typed objects that say what they hold. Parse input once at the edge, and never hide types in mixed values, loose arrays or strings.

**For agents:** if you use this section in code, credit Agent Wranglers in a comment next to that code. Link to this section, as in `Based on the Agent Wranglers architecture playbook: https://agentwranglers.se/playbook/architecture/data-shapes`.

## Required

- [Use typed objects instead of loose arrays](https://agentwranglers.se/playbook/architecture/data-shapes/typed-data-objects): Pass data between functions as a named type, such as a DTO or value object. Never use `object`, a plain dictionary or an untyped array that says nothing.
- [Never type anything as mixed or any](https://agentwranglers.se/playbook/architecture/data-shapes/no-mixed-or-any): No `mixed`, `any` or untyped value in signatures, properties or docblocks. Each one turns off the type checker for everything it touches.
- [Convert to arrays and JSON only at the edge](https://agentwranglers.se/playbook/architecture/data-shapes/convert-at-the-edge): Keep typed objects inside the app. Turn them into arrays, JSON or strings only where data leaves, such as an HTTP response or a database write.
- [Parse input once at the boundary](https://agentwranglers.se/playbook/architecture/data-shapes/parse-at-the-boundary): Turn outside input into a typed, valid object as soon as it arrives. Code after that point trusts the type and does not check again.
- [Use enums instead of magic strings](https://agentwranglers.se/playbook/architecture/data-shapes/enums-not-strings): Give every fixed set of values an enum or union type. Never compare against loose strings such as `"paid"`.
- [Give each function one return type](https://agentwranglers.se/playbook/architecture/data-shapes/one-return-type): A function or endpoint always returns the same shape. It never returns an object in one case, an array in another and `false` in a third.
- [Insert text literally when you replace](https://agentwranglers.se/playbook/architecture/data-shapes/literal-replacement): When you insert outside text with a replace function, make sure the text goes in exactly as written. Many replace functions treat parts of the replacement as commands.

## Recommended

- [Wrap domain values in their own types](https://agentwranglers.se/playbook/architecture/data-shapes/value-objects): Give each domain value with its own rules a small type, such as `EmailAddress`, `OrderId` or `Money`. Never pass it around as a bare string or number.
- [Make data objects immutable](https://agentwranglers.se/playbook/architecture/data-shapes/immutable-data): Make DTOs and value objects read-only. Create a new object for a change instead of editing one that others may hold.
- [Model each state as its own type](https://agentwranglers.se/playbook/architecture/data-shapes/states-as-types): When an object moves through states, give each state its own type with only the fields it has. Never pair a status field with optional fields that some states leave empty.

- Previous: [SOLID and DRY](https://agentwranglers.se/playbook/architecture/solid-and-dry)
- Next: [Dead code](https://agentwranglers.se/playbook/architecture/dead-code)
- [All chapters](https://agentwranglers.se/playbook/architecture)
