---
title: "How-To: Edit Components"
description: "Task recipe for editing ECS components through canonical authoring actions instead of raw Project Graph writes."
engineVersion: v1.0.234
date: 2026-09-28
license: "(c) Gessa, proprietary. Cite with attribution to https://gessa.ai/docs/. Terms: https://gessa.ai/terms/."
canonical: https://gessa.ai/docs/how-to/edit-components/
---

# How-To: Edit Components

Add and edit ECS components on entities the right way, through canonical authoring actions, so backend authority stays the single source of truth. ECS components are the engine's atomic contracts (under ADR 0020): they replicate, they are validated against a versioned schema, and they are consumed by the runtime and renderer. You edit a component by **invoking an action**, never by hand-writing the Project Graph.

This page describes the canonical authoring flow for v1. The engine is pre-launch and its readiness rows are unaccepted, so treat this as the intended contract surface rather than a guarantee of a finished end-to-end run; status tracks the [v1 readiness ledger](../../../cycles/v1-engine-readiness-loop/FEATURE_LEDGER.json).

## The component set is generated and fixed

The set of **built-in ECS components** in v1 is fixed by code. The inventory (categories, field contracts, contract versions, packs, and runtime/renderer consumers) is **Tier-2 generated** from `packages/ecs/src/index.ts` (`COMPONENT_TYPE_DEFINITIONS`) by `scripts/gen-component-docs.ts`. Read the field tables there; never restate them:

- [`docs/spec/generated/component-types.md`](../../../spec/generated/component-types.md): the canonical inventory.
- [`docs/spec/COMPONENT_TYPE_DEFINITIONS.md`](../../../spec/COMPONENT_TYPE_DEFINITIONS.md): the companion definitions surface.
- [Reference: ECS Components](../reference/ecs-components.md): the thin pointer page.

{% generated-reference file="docs/spec/generated/component-types.md" label="ECS component inventory" /%}

Built-in components are atomic engine contracts. Gameplay patterns (health, damage, spawn pools, inventories) are **script patterns**, not ECS atomics; you author those with [GessaScript](write-gessascript.md), not by inventing a component. A few representative built-ins you will edit often: `TransformComponent` (placement), `RenderableComponent` (visual presence), `ColliderComponent` and `RigidBodyComponent` (physics), and `CameraComponent` (viewpoint). Confirm the exact field contract for any component in the generated inventory before authoring it.

## The rule: no raw graph writes

{% warning severity="critical" title="Do not mutate the Project Graph directly" %}
Edit components only through the canonical authoring path, the workbench Build surface, the documented Action Catalog verb, or the semantic MCP tool. Raw Project Graph writes bypass schema validation, replication, and the single mutation-authority model, creating a second unvalidated source of truth. They are forbidden.
{% /warning %}

The canonical authoring path has one entry per surface, all lowering to the **same action**:

- **In the workbench:** the Build surface and the component inspector. The editor validates field edits against the canonical schema before they are applied.
- **From an agent or MCP client:** the semantic tool `project_add_component` (add or replace a complete component; `project_remove_component` to drop one). See [How-To: Use MCP Tools](use-mcp-tools.md).
- **The underlying verb:** all of the above lower to the Action Catalog action `project.entity.component.set` (and `project.entity.component.delete` to remove). This is exposed on the `ui`, `mcp`, `ai`, and `sdk` surfaces: one verb, every caller. See the [Action Catalog](../reference/action-catalog.md).

Because there is exactly one mutation authority, "editing a component" *means* "invoking `project.entity.component.set`" regardless of who you are. See [Explanation: Backend Authority](../explanation/backend-authority.md).

## Discover the schema first

A component is a typed contract, so author it against its schema rather than guessing field names. For agents, the discovery tool is `engine_get_component_schema`, which returns one built-in component's field contract plus a UI control-hint projection.

{% ai-context audience="mcp" priority="must" %}
Treat `fieldContracts` as authoritative; the control-hint schema is only a UI projection. Call `engine_list_component_types` to see what exists, `engine_get_component_schema` to read one component's contract, then `project_add_component` to author the value. Do not invent component names, only the built-ins in that inventory are real ECS atomics; everything else is a script pattern or project-defined metadata.
{% /ai-context %}

## The authoring recipe

{% recipe id="edit-component-canonical" goal="Add or edit a component value through the canonical action, then confirm" audience="both" %}

1. **Select the entity** you want to edit (in the workbench) or resolve its handle (via `project_search_entities`, or `project_get_graph_snapshot` for a broad view).
2. **Discover the component contract.** Read its field table in [`component-types.md`](../../../spec/generated/component-types.md), or call `engine_get_component_schema` for the live contract and control hints.
3. **Set fields within the contract.** In the workbench, edit the component in the inspector; the editor validates against the canonical schema. From an agent, call `project_add_component` with values that satisfy the field contract.
4. **Let the authority validate.** The action `project.entity.component.set` validates, applies, and replicates. An invalid value is rejected by the authority, not silently accepted.
5. **Confirm the change persisted.** Re-read the entity (`project_get_entity`) or the graph snapshot; what you see is a projection of authoritative state, so trust the receipt rather than your local copy.

{% /recipe %}

## Why `project_apply_transaction` is an escape hatch, not the path

There is a privileged low-level tool, `project_apply_transaction` (action `project.transaction.apply`), that applies raw Project Graph transactions. It requires a `privileged_authoring_reason` *precisely so that agents cannot accidentally choose it for normal authoring*. It exists for import and test-only paths. For component editing it is the wrong tool: it skips the typed component authoring contract that `project_add_component` enforces. If a semantic authoring tool exists for your edit (and for components it does) use it.

## Related

- [Reference: ECS Components](../reference/ecs-components.md): the generated field tables.
- [How-To: Use MCP Tools](use-mcp-tools.md): discovery-first authoring from an agent.
- [Explanation: The Project Graph](../explanation/project-graph.md): why direct writes are forbidden.
- [Explanation: Backend Authority](../explanation/backend-authority.md): the one-mutation-authority model these actions enforce.

Status: this page documents the canonical component-authoring flow for v1. End-to-end runnable status tracks the [v1 readiness ledger](../../../cycles/v1-engine-readiness-loop/FEATURE_LEDGER.json); the engine is pre-launch.
