> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formae.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Deal with out-of-band changes

> Someone changed your infrastructure outside formae. See how formae detects the drift on the next reconcile, then absorb the change into your code or discard it.

Infrastructure changes outside your code more often than you would like. A teammate
tightens a setting in the console, an incident responder adds a tag, an autoscaler
rewrites a value. formae's job is to keep your code and your running infrastructure
in agreement, so when reality drifts it tells you, and it does not silently paper
over the difference. This guide walks a real drift end to end: you change a resource
in the AWS console, formae detects it, and you either pull the change into your code
or discard it.

It uses the Lifeline foundation example, `basic_infrastructure.pkl`, which
provisions a VPC, an internet gateway, subnets, routing, and security groups.

## Set the scene

Apply the foundation so formae is managing it:

```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
formae apply --mode reconcile basic_infrastructure.pkl
```

All fifteen resources come up, and the stack is now under management. Your code and
your infrastructure agree.

## Change something outside formae

Now make a change the way a teammate in a hurry would: in the AWS console, open the
internet gateway that the foundation created and add a tag, `Owner = platform-team`.
Leave everything else alone.

<Frame caption="Adding a tag to the internet gateway directly in the AWS console, outside formae.">
  <img src="https://mintcdn.com/platform-engineering-labs/jhTeS4-asNTK2_YC/images/documentation/guides/out-of-band-changes/console-add-tag.png?fit=max&auto=format&n=jhTeS4-asNTK2_YC&q=85&s=660fa1268cce05f239bc578a943f54ee" alt="The AWS console tag editor adding an Owner tag to the lifeline internet gateway" width="3748" height="520" data-path="images/documentation/guides/out-of-band-changes/console-add-tag.png" />
</Frame>

The gateway now carries a tag that exists nowhere in your code. Your infrastructure
has drifted from its source of truth.

## formae detects the drift

The agent synchronizes with your cloud on an interval, reading the resources it
manages and noticing anything that changed underneath it. Within a sync cycle it
sees the new tag on the gateway.

<Tabs>
  <Tab title="CLI">
    Reconcile the foundation as you normally would. formae reads the live state
    first, sees that the stack changed since the last reconcile, and stops rather
    than overwriting the change blindly:

    ```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
    formae apply --mode reconcile basic_infrastructure.pkl
    ```

    Instead of applying, formae opens an interactive screen listing every resource
    that drifted and lets you decide what to do, right here:

    <div className="fa-term">
      <div className="fa-term-body">  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(232,232,232)',fontWeight:'600'}}>formae</span> <span style={{fontWeight:'600'}} /><span style={{color:'rgb(255,133,51)',fontWeight:'600'}}>apply</span>                                                                                  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>reconcile rejected</span><br /><span style={{color:'rgb(85,85,102)'}}>────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(85,85,102)'}} /><br /><span style={{color:'rgb(85,85,102)'}} />  <span style={{color:'rgb(248,113,113)'}}>Your infrastructure changed outside formae since the last reconcile.</span><br /><br />  <span style={{color:'rgb(170,170,170)'}}>Keep a change: extract the resource, fold it into your code, then re-apply.</span><br />  <span style={{color:'rgb(170,170,170)'}}>Press </span><span style={{color:'rgb(170,170,170)',fontWeight:'600'}} /><span style={{color:'rgb(129,209,219)',fontWeight:'600'}}>r</span><span style={{color:'rgb(170,170,170)'}}> to discard all out-of-band changes and re-apply your code with --force.</span><br /><br />  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(232,232,232)',fontWeight:'600'}}>Stack: lifeline</span> <span style={{color:'rgb(153,153,153)'}}>(1 change)</span><br />  <span style={{color:'rgb(85,85,102)'}}>──────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(232,232,232)'}} /><span style={{color:'rgb(232,232,232)'}}>  ▸ \[x] update  lifeline-igw (AWS::EC2::InternetGateway)</span><br /><br />  <span style={{color:'rgb(170,170,170)'}}>1 selected</span><br /><span style={{color:'rgb(85,85,102)'}}>────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(85,85,102)'}} />  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(129,209,219)',fontWeight:'600'}}>e</span><span style={{color:'rgb(153,153,153)'}}>: extract selected</span>  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(129,209,219)',fontWeight:'600'}}>r</span><span style={{color:'rgb(153,153,153)'}}>: revert all (--force)</span>  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(129,209,219)',fontWeight:'600'}}>q</span><span style={{color:'rgb(153,153,153)'}}>: abort</span>                                                   <span style={{fontWeight:'600'}} /><span style={{color:'rgb(129,209,219)',fontWeight:'600'}}>?</span><span style={{color:'rgb(153,153,153)'}}>: help</span></div>
    </div>

    formae will not clobber the change. From this screen you choose: press `e` to
    extract the selected resource and keep the change, or `r` to revert all
    out-of-band changes. You now decide: absorb the change or discard it.
  </Tab>

  <Tab title="AI assistants">
    With the [formae MCP plugin](/documentation/guides/ai-coding-assistants)
    connected, just ask whether your code still matches reality:

    <div className="fa-convo">
      <div className="fa-convo-head">Conversation</div>
      <div className="fa-turn fa-you"><div className="fa-tag">You</div><div className="fa-body">Is my codebase still in sync with what's actually running?</div></div>
      <div className="fa-turn fa-bot"><div className="fa-tag">Assistant</div><div className="fa-body">Not quite. Since your last reconcile, one resource on the <code>lifeline</code> stack changed outside formae: the internet gateway <code>lifeline-igw</code> was updated. Something added a tag to it in the console. Do you want to absorb that change into your forma, or discard it?</div></div>
    </div>
  </Tab>
</Tabs>

## Absorb the change into your code

The tag is worth keeping, so make your code describe it. This is the path formae
offers on the rejection screen: extract the live resource, fold the change into your
forma, and re-apply.

<Tabs>
  <Tab title="CLI">
    <Steps>
      <Step title="Extract the drifted resource">
        On the rejection screen, with `lifeline-igw` selected, press `e`. formae
        asks where to write the resource and extracts it live, tag and all:

        <div className="fa-term">
          <div className="fa-term-body">  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(232,232,232)',fontWeight:'600'}}>formae</span> <span style={{fontWeight:'600'}} /><span style={{color:'rgb(255,133,51)',fontWeight:'600'}}>apply</span>                                                                                  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>reconcile rejected</span><br /><span style={{color:'rgb(85,85,102)'}}>────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(85,85,102)'}} /><br /><span style={{color:'rgb(85,85,102)'}} />  <span style={{color:'rgb(232,232,232)'}}>Extracting 1 resource as code:</span><br />    <span style={{color:'rgb(232,232,232)'}}>lifeline-igw</span><span style={{color:'rgb(153,153,153)'}}> (AWS::EC2::InternetGateway)</span><br /><br />  <span style={{color:'rgb(153,153,153)'}}>Extract to: </span><span style={{color:'rgb(232,232,232)'}}>./extracted-drift.pkl█</span><br /><br />  <span style={{color:'rgb(181,181,91)'}}>Don't apply this file directly. It holds only the selected resource(s), so</span><br />  <span style={{color:'rgb(181,181,91)'}}>reconciling it would delete every other resource in the stack.</span><br /><br />  <span style={{color:'rgb(232,232,232)'}}>Copy the values you want to keep into your forma, then re-apply with --force:</span><br />    <span style={{color:'rgb(232,232,232)'}}>formae apply --mode reconcile --force basic\_infrastructure.pkl</span></div>
        </div>

        Press enter to confirm. formae writes the file and reminds you that it holds
        only the selected resource, so you fold the values into your own forma
        rather than applying the file directly:

        <div className="fa-term">
          <div className="fa-term-body">Extracted 1 resource(s) to ./extracted-drift.pkl<br />Fold the values you want to keep into your forma, then re-apply with --force:<br />  formae apply --mode reconcile --force basic\_infrastructure.pkl</div>
        </div>
      </Step>

      <Step title="Fold the change into your forma">
        Copy the tag into the gateway's definition in your own code. In the Lifeline
        example the gateway lives in `network_resources.pkl`:

        ```kotlin theme={"languages":{"custom":["/languages/pkl.json"]}}
        hidden igw: internetgateway.InternetGateway = new {
          label = "lifeline-igw"
          tags {
            new { key = "Name"; value = formae.value(name + "-igw").setOnce }
            new { key = "Owner"; value = "platform-team" }
          }
        }
        ```
      </Step>

      <Step title="Re-apply, and the drift is gone">
        Reconcile again with `--force`. Your code now matches reality, so this
        re-applies your forma (tag included) and clears the drift flag on the stack:

        ```bash theme={"languages":{"custom":["/languages/pkl.json"]}}
        formae apply --mode reconcile --force basic_infrastructure.pkl
        ```

        The tag is now part of your committed infrastructure, not drift. Your code
        and your cloud describe the same thing again.
      </Step>
    </Steps>
  </Tab>

  <Tab title="AI assistants">
    <div className="fa-convo">
      <div className="fa-convo-head">Conversation</div>
      <div className="fa-turn fa-you"><div className="fa-tag">You</div><div className="fa-body">Absorb it. That tag should be part of our code going forward.</div></div>
      <div className="fa-turn fa-bot"><div className="fa-tag">Assistant</div><div className="fa-body">I extracted the live internet gateway and added its <code>Owner = platform-team</code> tag to the gateway definition in <code>network\_resources.pkl</code>. Reconciling now reports no changes, so your forma and the running stack agree again and the tag is under management. Want me to commit the change?</div></div>
      <div className="fa-turn fa-you"><div className="fa-tag">You</div><div className="fa-body">Yes, commit it.</div></div>
    </div>
  </Tab>
</Tabs>

## Or discard the change

If the change was a mistake or a temporary hack, do the opposite from the same
rejection screen: press `r` to revert all out-of-band changes. formae shows exactly
what it will undo, down to the field, and asks you to confirm:

<div className="fa-term">
  <div className="fa-term-body">  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(232,232,232)',fontWeight:'600'}}>formae</span> <span style={{fontWeight:'600'}} /><span style={{color:'rgb(255,133,51)',fontWeight:'600'}}>apply</span>                                                                                  <span style={{fontWeight:'600'}} /><span style={{color:'rgb(248,113,113)',fontWeight:'600'}}>reconcile rejected</span><br /><span style={{color:'rgb(85,85,102)'}}>────────────────────────────────────────────────────────────────────────────────────────────────────────────────────</span><br /><span style={{color:'rgb(85,85,102)'}} /><br /><span style={{color:'rgb(85,85,102)'}} />  <span style={{color:'rgb(232,232,232)'}}>This will revert ALL out-of-band changes by re-applying with --force:</span><br /><br />    <span style={{color:'rgb(181,181,91)'}}>revert</span><span style={{color:'rgb(232,232,232)'}}>  lifeline-igw</span><span style={{color:'rgb(153,153,153)'}}> (AWS::EC2::InternetGateway)</span>      <span style={{color:'rgb(153,153,153)'}}>Tags</span><br /><br />  <span style={{color:'rgb(232,232,232)'}}>Are you sure? This cannot be undone. </span><span style={{color:'rgb(181,181,91)'}}>(y/N)</span></div>
</div>

Confirm with `y` and formae re-applies your unchanged code with `--force`, removing
the tag and returning the gateway to exactly what your code describes. You can also
run `formae apply --mode reconcile --force basic_infrastructure.pkl` directly.

<Warning>
  Reverting overwrites every out-of-band change on the stack, not just the one you have
  in mind. Extract and review the changes first if you are not certain what you are
  discarding.
</Warning>

## See also

* [Incidents and recovery](/documentation/guides/incidents-and-recovery): absorb or discard a change you made yourself with a patch during an incident.
* [Synchronization](/documentation/concepts/synchronization): how the agent reads live state and detects out-of-band changes.
* [Apply modes](/documentation/concepts/apply-modes): reconcile versus patch, and why a soft reconcile stops on drift.
