The @stratt/ir package introduced a platform-agnostic intermediate representation between STRATT chains and execution platforms. Instead of compiling chains directly to n8n (which the n8n-exporter did), chains now compile to IR first, then IR compiles to any target. This added one indirection but unlocked three targets immediately: n8n JSON, executable TypeScript, and LangGraph Python.
Key learning: The IR is the stable contract. Chain semantics (steps, gates, dependencies, agents) change rarely. Platform formats (n8n node types, LangChain APIs) change constantly. The IR absorbs the chain semantics once, and target compilers handle platform drift independently. Adding a fourth target (e.g., OpenAI Batch API) requires only implementing (IRProgram) → CompileResult — about 50 lines — with zero changes to the IR or chain schema.
Applicable pattern: When you have one producer and N consumers, insert an interchange format. The cost is one extra compilation step; the benefit is that producers and consumers evolve independently. The IR must be serializable (JSON) so it can be inspected, cached, and version-compared.