Agent Wranglers

Coupling Required

Pass state in instead of sharing globals

Never share changeable data through globals, singletons or module-level variables when it changes how code behaves. Pass state in, and return new state out.

How to do it

Keep settings in one object built at startup and passed to the code that needs it. Make shared values constant. Replace singletons with one instance created at startup and injected. A module-level cache of pure results is allowed, such as memoised formatters or ETags of fixed files. It only saves work, so it never changes an answer.

Example

# Bad: any function can change it, and tests leak into each other
current_currency = "EUR"

def price(amount):
    return f"{amount} {current_currency}"

# Good: the value is passed in
def price(amount: Decimal, currency: Currency) -> str:
    return f"{amount} {currency.code}"
// Bad
let currentCurrency = 'EUR';
const price = (amount: number) => `${amount} ${currentCurrency}`;

// Good
const price = (amount: number, currency: Currency) => `${amount} ${currency.code}`;

How to check

Tests run in random order and still pass, for example with Jest --randomize, pytest-randomly or PHPUnit --order-by=random. Pylint global-statement flags writes to globals. In JavaScript, a grep fails let or var at the start of a line, which marks a module-level variable.

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/coupling/no-global-state.