Files
approved-plan-continuity-ha…/plugins/continuity/AGENT_GUIDE.md

19 KiB

Continuity Plugin MVP: Agent Installation and Operations Guide

Audience: OpenClaw agents / implementers

This is a hands-on runbook and checklist, not a conceptual overview. If you only need to know whether to install it, how to wire it, and how to verify it, start here instead of reading the full README first.

0. When should you install this plugin?

Install this plugin if any of the following are true in your workspace:

  • You run approved-plan style long-running or multi-step tasks.
  • You do not want the agent to treat a finished task as “the whole job is done” by default.
  • You need the agent to decide whether there is a next task to dispatch inside the same approved plan.
  • You need a dispatch receipt as evidence that the next step was actually dispatched, instead of only saying so in prose.
  • You already use hooks/force-recall/handler.ts and want to inject the approved-plan continuity gate into the agent prompt.
  • You do not have a force-recall hook, but you do have your own preflight / planner / orchestrator and want to call the generic continuity adapter directly.

Cases where you can skip it for now

You can defer installation, or treat this plugin as reference only, when:

  • Your workspace has no approved-plan / auto-chain / dispatch flow.
  • You only need ordinary single-turn chat behavior and do not need a continuity hard gate.
  • You do not have a force-recall hook and you also do not plan to add generic glue code in your own host/orchestrator.

1. Installation target and expected outcome

After installation, the minimum expected result is:

  • your host (for example force-recall or your own preflight path) can load plugins/continuity/src/index.mjs
  • the host calls one of these during preflight:
    • runForceRecallContinuityAdapter(...)
    • runGenericPreflightContinuityAdapter(...)
    • runManualContinuityPreflight(...)
  • the agent prompt contains a visible [APPROVED_PLAN_CONTINUITY_GATE] ... [/APPROVED_PLAN_CONTINUITY_GATE] block
  • when an approved-plan task is finished but there is no real next-step dispatch receipt, the gate blocks an incorrect closure
  • plugin tests and the relevant host smoke path pass

2. Where should it live?

Standard location

Place the plugin here inside the workspace:

<workspace>/plugins/continuity

Recommended layout (adjust as needed for your host):

<workspace>/
  hooks/
    force-recall/
      handler.ts
      HOOK.md
  plugins/
    continuity/
      AGENT_GUIDE.zh-TW.md
      AGENT_GUIDE.md
      README.zh-TW.md
      README.md
      HOOK.md
      GENERIC_INTEGRATION.zh-TW.md
      GENERIC_INTEGRATION.md
      package.json
      examples/
      src/
      test/
  scripts/
    test_force_recall_long_task_preflight.mjs

Actual path for this document set

/home/alice/.openclaw/workspace/plugins/continuity

3. Pre-install checklist

Before you start, confirm:

  • your workspace has hooks/force-recall/handler.ts, or you already know which generic/manual host path will call the plugin
  • your workspace has scripts/test_force_recall_long_task_preflight.mjs if you intend to use the force-recall path
  • your workspace is willing to adopt the approved-plan continuity hard gate
  • you understand that force-recall is the most mature adapter, but not the only host path
  • you understand that the receipt is a minimum contract, not a complete workflow engine

Quick checks:

cd <workspace>
ls plugins/continuity/package.json
ls plugins/continuity/src/index.mjs
ls hooks/force-recall/handler.ts
ls scripts/test_force_recall_long_task_preflight.mjs

If you do not have force-recall, see GENERIC_INTEGRATION.zh-TW.md or GENERIC_INTEGRATION.md for the generic/manual path.


4. Required files

Required files

At minimum, you should have:

plugins/continuity/
  package.json
  src/index.mjs
  src/adapters/force-recall.mjs
  src/adapters/generic-preflight.mjs
  src/config/defaults.mjs
  src/config/schema.mjs
  src/continuity/evaluator.mjs
  src/continuity/receipt-validator.mjs
  src/continuity/receipt-store.mjs
  examples/openclaw.continuity.example.json
  examples/approved-plan-receipt.example.json
plugins/continuity/
  README.zh-TW.md
  README.md
  HOOK.md
  AGENT_GUIDE.zh-TW.md
  AGENT_GUIDE.md
  GENERIC_INTEGRATION.zh-TW.md
  GENERIC_INTEGRATION.md
  test/continuity.config.test.mjs
  test/continuity.receipt-validator.test.mjs
  test/continuity.receipt-store.test.mjs
  test/continuity.evaluator.test.mjs
  test/continuity.plugin.test.mjs
  test/continuity.smoke.test.mjs

If files are missing, what should you restore first?

Priority order:

  1. src/index.mjs
  2. src/adapters/force-recall.mjs
  3. src/adapters/generic-preflight.mjs
  4. src/continuity/evaluator.mjs
  5. src/continuity/receipt-validator.mjs
  6. src/continuity/receipt-store.mjs
  7. examples/openclaw.continuity.example.json
  8. test/continuity.smoke.test.mjs

5. Direct installation steps

Path A: you are already inside the same repo/workspace

  • confirm plugins/continuity exists
  • confirm package.json and src/index.mjs exist
  • confirm your chosen host entrypoint exists

Verification:

cd <workspace>
find plugins/continuity -maxdepth 3 -type f | sort

Path B: you want to copy it into another OpenClaw workspace

From the source workspace:

cd <source-workspace>
rsync -av plugins/continuity/ <target-workspace>/plugins/continuity/

Then verify inside the target workspace:

cd <target-workspace>
find plugins/continuity -maxdepth 3 -type f | sort

6. How to apply the example config

Step 1: copy the example continuity config

Source example:

plugins/continuity/examples/openclaw.continuity.example.json

Example content:

{
  "enabled": true,
  "planMatchers": ["approved-plan"],
  "legalTerminalStates": [
    "waiting_user",
    "blocked",
    "pending_verification"
  ],
  "receiptDir": "state/approved-plan-continuity",
  "requireRealDispatchReceipt": true,
  "allowReplyClosureWithoutDispatch": false,
  "debug": false,
  "adapter": {
    "forceRecall": {
      "enabled": true,
      "injectBlockLabel": "APPROVED_PLAN_CONTINUITY_GATE"
    },
    "genericPreflight": {
      "enabled": true,
      "injectBlockLabel": "APPROVED_PLAN_CONTINUITY_GATE"
    }
  }
}

Step 2: only change the minimum fields first

Usually you only need to verify these first:

  • enabled
  • planMatchers
  • legalTerminalStates
  • receiptDir
  • requireRealDispatchReceipt
  • allowReplyClosureWithoutDispatch
  • adapter.forceRecall.enabled
  • adapter.forceRecall.injectBlockLabel
  • adapter.genericPreflight.enabled
  • adapter.genericPreflight.injectBlockLabel

Situation A: you want the current approved-plan MVP behavior

Use the example as-is in most cases:

  • planMatchers = ["approved-plan"]
  • legalTerminalStates = ["waiting_user", "blocked", "pending_verification"]
  • requireRealDispatchReceipt = true
  • allowReplyClosureWithoutDispatch = false

Situation B: your planner uses a different plan name

Adjust:

{
  "planMatchers": ["your-approved-plan-name"]
}

Situation C: you want a different injected block label

Adjust:

{
  "adapter": {
    "genericPreflight": {
      "enabled": true,
      "injectBlockLabel": "YOUR_CONTINUITY_GATE"
    }
  }
}

Step 4: create the receipt directory up front

cd <workspace>
mkdir -p state/approved-plan-continuity

7. How to wire the host/hook

7.1 Integration points to confirm

The most mature integration point is still:

hooks/force-recall/handler.ts

But that is no longer the only path. A generic or manual preflight host can also call the plugin directly.

A typical host-side flow should look like this:

  1. run long-task preflight / wrapper, or equivalent host preflight
  2. run gate lock if you have one
  3. run auto-chain planner, or derive next action in your own planner
  4. load the continuity plugin
  5. call the appropriate adapter
  6. prepend the returned continuity block into the prompt body shown to the agent

At minimum, look for these symbols

  • plugins/continuity/src/index.mjs
  • runForceRecallContinuityAdapter
  • runGenericPreflightContinuityAdapter
  • runManualContinuityPreflight
  • APPROVED_PLAN_CONTINUITY_GATE

Example checks:

cd <workspace>
grep -n "runForceRecallContinuityAdapter" hooks/force-recall/handler.ts
grep -n "APPROVED_PLAN_CONTINUITY_GATE" hooks/force-recall/handler.ts

7.2 Minimum force-recall wiring example

import plugin from './plugins/continuity/src/index.mjs';

const out = plugin.runForceRecallContinuityAdapter({
  config: plugin.defaultConfig,
  wrapperResult,
  autoChainPlanResult,
});

if (out?.block) {
  context.bodyForAgent = `${out.block}\n${context.bodyForAgent}`;
}

7.3 Minimum generic/manual wiring example

If you do not have force-recall, feed your own preflight result into the generic adapter:

import plugin from './plugins/continuity/src/index.mjs';

const out = plugin.runGenericPreflightContinuityAdapter({
  config: plugin.defaultConfig,
  source: {
    planId: 'approved-plan-1',
    currentTask: 'task-3',
    taskState: 'complete',
    nextTaskKnown: true,
    sameApprovedPlan: true,
    taskBoundaryStop: true,
    nextTaskId: 'task-4',
    nextDerivedAction: { type: 'message_subagent', task: 'continue' },
    replyClosureState: 'completed',
    dispatchReceipt: null,
  },
});

If you only need a one-off manual continuity preflight:

const out = plugin.runManualContinuityPreflight({
  config: plugin.defaultConfig,
  planId: 'approved-plan-1',
  currentTask: 'task-3',
  taskState: 'complete',
  nextDerivedAction: { type: 'message_subagent', task: 'continue' },
  replyClosureState: 'waiting_user',
});

7.4 Real checks implementers should perform

  • the host can import plugins/continuity/src/index.mjs
  • the chosen adapter function exists
  • relevant input is passed in
  • config is passed in, at least defaultConfig to start
  • when out.block is non-empty, it is prepended to the agent-facing prompt/body
  • the final agent prompt really contains the continuity gate block

7.5 Relationship between receipt and continuity input

If your flow really dispatches the next step, do not only say “dispatched” in plain text. Emit a real dispatchReceipt.

Minimum receipt shape:

  • planId
  • currentTask
  • nextDerivedAction
  • dispatchedAt
  • dispatchRunId
  • childSessionKey
  • replyClosureState

Reference example: plugins/continuity/examples/approved-plan-receipt.example.json


8. Suggested implementation workflow

Checklist: first-time plugin integration into an existing workspace

  • create/copy plugins/continuity
  • confirm src/index.mjs can be loaded by the host
  • confirm the example config is readable
  • create state/approved-plan-continuity/
  • confirm your host has a continuity adapter call site
  • confirm the continuity block is prepended into the agent prompt/body
  • if a real dispatch occurs, persist a receipt
  • run plugin tests
  • run the host smoke path
  • confirm the injected prompt block is present

Checklist: first-time receipt persistence

  • prepare a valid receipt object
  • validate it with validateReceipt() / isValidReceipt() first
  • persist it with writeReceipt({ receiptDir, receipt })
  • confirm the receipt file lands in state/approved-plan-continuity/
  • rerun continuity smoke tests so you do not mistake “looks like a receipt” for a real passing state

9. How to run smoke tests after installation

Minimum smoke test

Run the plugin tests first:

cd <workspace>/plugins/continuity
npm test

If you only want a quick plugin-only verification:

cd <workspace>/plugins/continuity
node test/continuity.smoke.test.mjs

Hook integration smoke test

cd <workspace>
node scripts/test_force_recall_long_task_preflight.mjs
node --check hooks/force-recall/handler.ts

This order makes failures easier to localize:

  1. plugin unit/integration tests
cd <workspace>/plugins/continuity
npm test
  1. hook syntax check
cd <workspace>
node --check hooks/force-recall/handler.ts
  1. hook preflight smoke test
cd <workspace>
node scripts/test_force_recall_long_task_preflight.mjs
  1. manual inspection: confirm the block is really injected

Look for:

[APPROVED_PLAN_CONTINUITY_GATE]

10. Smoke test success criteria

The minimum install is successful only if all of these are true:

  • npm test passes
  • node --check hooks/force-recall/handler.ts passes, if you use that path
  • node scripts/test_force_recall_long_task_preflight.mjs passes, if you use that path
  • the continuity gate block is visible in test output or debug prompt output
  • when there is no receipt, the gate fails / hard-gates the missing-dispatch case
  • legal terminal states such as waiting_user, blocked, or pending_verification are not misclassified

11. What to check first when something fails

Follow this order. Do not start by changing random code.

Layer 1: path and file existence

  • plugins/continuity/src/index.mjs exists
  • your host entrypoint exists
  • plugins/continuity/examples/openclaw.continuity.example.json exists
  • plugins/continuity/examples/approved-plan-receipt.example.json exists

Commands:

cd <workspace>
ls plugins/continuity/src/index.mjs
ls hooks/force-recall/handler.ts
ls plugins/continuity/examples/openclaw.continuity.example.json
ls plugins/continuity/examples/approved-plan-receipt.example.json

Layer 2: is the host really calling the plugin?

  • your host imports or dynamically loads the continuity plugin
  • your host calls the correct adapter function
  • your host prepends out.block into the agent prompt/body

Layer 3: is the config sensible?

Check first:

  • enabled === true
  • the chosen adapter is enabled
  • planMatchers matches your approved-plan name
  • receiptDir is writable
  • requireRealDispatchReceipt matches your intended policy
  • allowReplyClosureWithoutDispatch has not accidentally weakened the gate

Layer 4: is the receipt real, not placeholder data?

Common problems:

  • only “planning to dispatch”, but no real receipt
  • incomplete receipt shape
  • empty dispatchRunId or childSessionKey
  • invalid replyClosureState
  • writing to the wrong directory

Layer 5: is the host preflight data sufficient?

The continuity adapter depends on preflight inputs such as:

  • wrapper/planner output in the force-recall path
  • normalized continuity source data in the generic path

So verify:

  • the host really carries forward long-task / approved-plan state
  • the planner really produced derivedAction / nextDerivedAction
  • the continuity input can be built from host data
  • closure state is derived correctly

12. Quick debugging commands

Run the plugin test suite

cd <workspace>/plugins/continuity
npm test

Check hook syntax

cd <workspace>
node --check hooks/force-recall/handler.ts

Check continuity keywords in the handler

cd <workspace>
grep -n "runForceRecallContinuityAdapter" hooks/force-recall/handler.ts
grep -n "APPROVED_PLAN_CONTINUITY_GATE" hooks/force-recall/handler.ts

Check whether receipts are actually written

cd <workspace>
find state/approved-plan-continuity -maxdepth 2 -type f | sort

13. Current limitations

Accept these limitations before installation:

  • this plugin is an extracted approved-plan continuity hard gate, not a general workflow engine
  • force-recall is still the most mature adapter, but not the only adapter
  • if your workspace has no force-recall, you still need to connect host data into the generic/manual path yourself
  • config is still “module defaults + caller input”, not a full installer/registry flow
  • the receipt store only writes files; it does not manage retention, cleanup, or indexing
  • the receipt validator checks only the minimum contract; it does not deeply validate every nextDerivedAction semantic variant
  • if you only perform dry-run planning and never create a real dispatch receipt, the gate may still fail by design; that is expected behavior, not a bug

If you hand this plugin to another agent or implementer, the handoff should at least satisfy all of the following:

  • they understand the plugin purpose without re-reading the entire conversation
  • they know where the files should live
  • they know which files must be copied
  • they know how to wire the force-recall hook, if applicable
  • they know which example config fields to check first
  • they know how to run smoke tests
  • they know the first debugging layers to inspect
  • they understand the current limits and do not mistake this for a full workflow framework

If all eight points are covered, this has reached the “agent can follow it” bar.


15. One-page execution summary

If you are in a hurry, do only these:

  1. put the plugin here:
<workspace>/plugins/continuity
  1. confirm the host is wired to:
  • plugins/continuity/src/index.mjs
  • runForceRecallContinuityAdapter(...) or runGenericPreflightContinuityAdapter(...)
  • prepend out.block into the agent prompt/body
  1. apply the example config:
plugins/continuity/examples/openclaw.continuity.example.json
  1. create the receipt directory:
mkdir -p <workspace>/state/approved-plan-continuity
  1. run tests:
cd <workspace>/plugins/continuity && npm test
cd <workspace> && node --check hooks/force-recall/handler.ts
cd <workspace> && node scripts/test_force_recall_long_task_preflight.mjs
  1. confirm the prompt contains:
[APPROVED_PLAN_CONTINUITY_GATE]
  1. confirm that without a real dispatch receipt, the task is not incorrectly treated as completed.

16. Reference files

  • plugins/continuity/README.zh-TW.md
  • plugins/continuity/README.md
  • plugins/continuity/HOOK.md
  • plugins/continuity/GENERIC_INTEGRATION.zh-TW.md
  • plugins/continuity/GENERIC_INTEGRATION.md
  • plugins/continuity/examples/openclaw.continuity.example.json
  • plugins/continuity/examples/approved-plan-receipt.example.json
  • hooks/force-recall/handler.ts
  • scripts/test_force_recall_long_task_preflight.mjs

If you need the Traditional Chinese operator version, use AGENT_GUIDE.zh-TW.md first; this file is the English counterpart.