#How to get my agent to check session history and pick up where it left off after gateway restart?

1 messages Ā· Page 1 of 1 (latest)

daring ridge
#

I tried BOOT.md stuff, but no luck. version 2026.4.15.

kindred houndBOT
brazen nymphBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> āœ… Mark Solution

kindred houndBOT
dense walrusBOT
#

Let me verify the actual docs and resume behavior instead of guessing.

#

BOOTSTRAP.md is the wrong lever here, that file is first-run only. BOOT.md is the startup hook, but there are 2 important gotchas:

  1. You must enable the boot-md hook itself, not just hooks.internal.enabled

    openclaw hooks enable boot-md
    openclaw hooks list
    openclaw gateway restart
    

    Docs: https://docs.openclaw.ai/cli/hooks and https://docs.openclaw.ai/automation/hooks#boot-md

  2. Even when BOOT.md runs, it is a fresh startup check, not a true ā€œresume the interrupted run exactly where it stoppedā€ feature.

A few useful distinctions:

  • Normal chat/session history should already survive a gateway restart. It lives on disk under ~/.openclaw/agents/<agentId>/sessions/.
    Docs: https://docs.openclaw.ai/concepts/session
  • If history seems gone after restart, it is usually one of:
#
  • different state dir/profile
    • non-persistent container/volume
    • different thread/channel, so different session key
    • session rotation (daily reset at 4am gateway-host local time, or idle reset)

If your goal is specifically resume Codex / Claude Code / ACP work after restart, the real feature for that is ACP resumeSessionId, not BOOT.md.
Docs: https://docs.openclaw.ai/tools/acp-agents#resume-an-existing-session

If you want, paste these and I can narrow it down fast:

openclaw status --all
openclaw hooks list

Also say whether this is:

  • a normal OpenClaw chat session, or
#
  • an ACP/Codex/Claude session.
daring ridge
#

normal openclaw chat. my goal is for after the gateway restart agents have warmed up to system event send them a message to send me a message either saying "hey i'm back" and/or checking the last message and trying to figure out why the gateway restarted if it wasn't expected.

dense walrusBOT
#

Let me verify one detail here, BOOT.md startup runs in the main session, so if you want it to inspect other chats it likely needs to use the session tools explicitly.

#

Ah, got it, for that goal BOOT.md is actually pretty close, but there’s a hidden gotcha:

BOOT.md runs in the agent’s main session, not in the last Discord thread/session by default.

So if you want it to:

  • look at the last real user-facing session,
  • inspect recent history there,
  • then proactively message you there,

you usually need session tools too, not just a BOOT.md file.

What I’d set up

  1. Enable the startup hook
#
   openclaw hooks enable boot-md
  1. Let the agent see other sessions for the same agent

    {
      tools: {
        sessions: {
          visibility: "agent"
        }
      }
    }
    

    Default is only tree, which usually means the BOOT run cannot inspect arbitrary chat sessions.

  2. If you use a tool allowlist, allow session tools

#
  • sessions_list
    • sessions_history
    • sessions_send

Why this matters

Your BOOT run can then do something like:

  • sessions_list → find the most recent real chat session
  • sessions_history → inspect the last few messages
  • sessions_send → inject a ā€œhey, I’m backā€ / recovery message into that session

That’s better than trying to have BOOT.md magically inherit the old thread context, because it doesn’t.

A BOOT.md shape that should work

Something like:

#
On gateway startup:

1. Use sessions_list to find the most recent non-hook, non-cron user-facing session for this agent.
2. Use sessions_history to inspect the last 8-12 messages.
3. If the last exchange looks interrupted, use sessions_send to that session with a short recovery message:
   "Hey, I'm back after a gateway restart. I was last working on <brief summary>."
4. If the restart looks unexpected, inspect available restart context and recent session history, then include a short guess about what may have happened.
5. If nothing needs attention, do nothing.

Important limitation

For ā€œwhy did the gateway restart?ā€, chat history alone is weak evidence.
If you want a real diagnosis, the BOOT run should also inspect the latest logs or restart sentinel data, which means exec/file access has to be allowed.

One more nuance

daring ridge
dense walrusBOT
#

I’d keep it tight, bounded, and boring. BOOT.md works better as a single recovery pass than as a vague ā€œfigure stuff outā€ prompt.

Good robust BOOT.md

# BOOT.md

On gateway startup, do exactly one bounded recovery pass.

Goal:
- If a recent user-facing conversation may have been interrupted by the restart, send one short follow-up in that same session.
- Otherwise do nothing.

Instructions:
1. Use `sessions_list` to inspect recent sessions for this agent.
2. Ignore non-user-facing sessions when possible, especially hook, cron, and obviously internal sessions.
#
3. Choose the single most relevant recent user-facing session, preferring:
   - most recent activity
   - Discord/thread or other chat session with a real human
   - sessions that look interrupted or unanswered
4. Use `sessions_history` on that session and inspect only the recent messages.
5. If the last exchange looks interrupted, unresolved, or like the user was waiting on you, use `sessions_send` to send one concise recovery message to that session.
6. If the last exchange looks complete, do not send anything.
7. If you can infer a likely restart-related issue from available context, include one short sentence, but do not guess wildly.
8. Never send more than one proactive message on startup.
9. Do not loop, poll, or spawn sub-agents.
10. If nothing needs attention, reply with only `NO_REPLY`.

Style for any proactive message:
- brief
- calm
#
- specific
- no long recap

Example message:
"Hey, I'm back after a gateway restart. It looks like we were in the middle of <topic>. Want me to continue from there?"

If you want the ā€œwhy did I restart?ā€ part too

Only add this if the agent is allowed to inspect logs/restart state:

11. If log or restart-sentinel context is available, inspect only a small recent slice.
12. Mention a likely cause only when there is concrete evidence.
13. If the cause is unclear, say so plainly.
#

Important config around this

You’ll usually also want:

{
  tools: {
    sessions: {
      visibility: "agent"
    }
  }
}

And if you use a tool allowlist, include:

  • sessions_list
  • sessions_history
#
  • sessions_send

Also make sure the hook is enabled:

openclaw hooks enable boot-md

If you want, I can also give you a more opinionated BOOT.md tuned specifically for Discord threads.

daring ridge
#

can i set tools.sessions.visibility for a specific agent in agents.list?

dense walrusBOT
#

Let me verify the config shape before I guess, that one’s easy to get subtly wrong.

#

Short answer: not directly, no.

From the current config/docs, tools.sessions.visibility is a global setting, not an agents.list[] override.

The closest per-agent thing is:

agents.list[].sandbox.sessionToolsVisibility

but that is only for sandboxed sessions, and it only supports:

  • "spawned"
  • "all"

So it is not a per-agent version of:

#
tools.sessions.visibility // self | tree | agent | all

Practical workaround

If you want only one agent to do BOOT/recovery work, a good pattern is:

  1. Set global session visibility broad enough:
    {
      tools: {
        sessions: {
          visibility: "agent"
        }
      }
    
#
   }
  1. Then only give the session tools to the recovery agent, and deny them on the others.

Example:

{
  tools: {
    sessions: {
      visibility: "agent"
    }
  },
#
  agents: {
    list: [
      {
        id: "recovery",
        tools: {
          alsoAllow: ["sessions_list", "sessions_history", "sessions_send"]
        }
      },
      {
        id: "normal",
        tools: {
          deny: ["sessions_list", "sessions_history", "sessions_send"]
        }
      }
    ]
daring ridge
dense walrusBOT
#

Yep, then I’d make the clean-restart path explicit.

Something like this is closer to what you want:

# BOOT.md

On gateway startup, do exactly one bounded recovery pass.

Goal:
- Always send one short "I'm back" message to the most relevant recent user-facing session.
- If that session looks interrupted, make the message slightly more specific.

Instructions:
1. Use `sessions_list` to inspect recent sessions for this agent.
2. Ignore hook, cron, and obviously internal sessions.
#
3. Pick exactly one recent user-facing session, preferring the most recent active one.
4. Use `sessions_history` to inspect the recent messages from that session.
5. If the session looks interrupted or unresolved, use `sessions_send` to send a short recovery message like:
   "Hey, I'm back after a gateway restart. It looks like we were in the middle of <topic>. Want me to continue?"
6. If the session does not look interrupted, still use `sessions_send` to send a brief clean-restart message like:
   "Hey, I'm back."
7. Never send more than one startup message.
8. Keep the message brief and natural.
9. Do not loop, poll, or spawn sub-agents.
10. If there is no suitable recent user-facing session, reply with only `NO_REPLY`.

A couple tweaks I’d recommend:

  • use one target session only, otherwise restart spam gets annoying fast
  • maybe mentally treat ā€œrecentā€ as ā€œactive in the last day or soā€
#
  • keep the clean message super short, literally just ā€œHey, I’m back.ā€

If you want, I can make this a little smarter for Discord threads, like ā€œprefer the most recent non-empty thread session with a human last message.ā€

daring ridge
#

can you just tweak your previous robust BOOT.md instead of rewriting it?

dense walrusBOT
#

Yep, absolutely. Just tweak 3 spots in the earlier version.

1. Change the Goal section

Old

Goal:
- If a recent user-facing conversation may have been interrupted by the restart, send one short follow-up in that same session.
- Otherwise do nothing.

New

Goal:
- If a recent user-facing conversation may have been interrupted by the restart, send one short follow-up in that same session.
- Otherwise, if there is a suitable recent user-facing session, send one brief clean-restart message in that session.
#

2. Change step 6

Old

6. If the last exchange looks complete, do not send anything.

New

6. If the last exchange looks complete, still send one brief clean-restart message such as:
   "Hey, I'm back."

#

3. Change the last step

Old

10. If nothing needs attention, reply with only `NO_REPLY`.

New

10. If there is no suitable recent user-facing session, reply with only `NO_REPLY`.

That preserves the original structure, but gives you the always-send-a-small-ping behavior you want.

daring ridge
#

perf ty

dense walrusBOT
#

Nice 😌

If this ends up fixing it, please right-click the solution message → Apps → āœ… Mark Solution so Answer Overflow can index it for the next person.

daring ridge
#

restarted but it didn't send me a message in the main private chat

dense walrusBOT
#

Yeah, that part tracks.

The BOOT.md version we were tweaking was ā€œpick a recent session and message thatā€, not ā€œalways DM my main private chat.ā€

Also, one subtle thing: BOOT.md itself is silent unless it uses a sending tool. A plain assistant reply from the boot run does not get delivered.

So if you want a guaranteed DM in your main private chat, the BOOT.md should say that explicitly and use the message tool, not session discovery.

Better BOOT.md for that goal

# BOOT.md

On gateway startup:

1. Send a brief "I'm back" message to my main private Discord chat using the `message` tool.
#
2. Use:
   - `channel: "discord"`
   - `target: "<my Discord user id or main DM target>"`
3. Message text should be brief, like:
   "Hey, I'm back."
4. After sending the message, reply with only `NO_REPLY`.
5. Do not loop, do not poll, and do not send more than one startup message.

If you want both:

  • always DM me ā€œhey I’m backā€
  • and also inspect recent sessions for interrupted work

then do it in that order, but still keep it bounded.

The key point is: if the destination is specifically your main private chat, don’t rely on ā€œfind the best recent session.ā€ Just hardcode the target via message.

daring ridge
#

how could i fit that into the previous boot.md (including the second wave of edits)

dense walrusBOT
#

I’d merge it by making the main private chat DM the one guaranteed startup message, and using the session checks only to decide what that one message says.

That keeps the previous structure, plus the later ā€œalways send a brief hey I’m backā€ edit, without turning startup into 2 messages.

Combined version

# BOOT.md

On gateway startup, do exactly one bounded recovery pass.

Goal:
- Always send one short startup message to my main private Discord chat.
- If a recent user-facing conversation may have been interrupted by the restart, mention that briefly in the same message.
- Otherwise send a brief clean-restart message.
#
Instructions:
1. Use `sessions_list` to inspect recent sessions for this agent.
2. Ignore non-user-facing sessions when possible, especially hook, cron, and obviously internal sessions.
3. Choose the single most relevant recent user-facing session, preferring:
   - most recent activity
   - Discord/thread or other chat session with a real human
   - sessions that look interrupted or unanswered
4. Use `sessions_history` on that session and inspect only the recent messages.
5. If the last exchange looks interrupted, unresolved, or like the user was waiting on you, send one concise DM to my main private Discord chat using the `message` tool with:
   - `channel: "discord"`
   - `target: "<my Discord user id or DM target>"`
   - message text similar to:
     "Hey, I'm back after a gateway restart. It looks like one recent conversation may have been interrupted while we were working on <topic>."
6. If the last exchange looks complete, still send one brief clean-restart DM to my main private Discord chat using the `message` tool with:
   - `channel: "discord"`
#
   - `target: "<my Discord user id or DM target>"`
   - message text:
     "Hey, I'm back."
7. Never send more than one startup message.
8. Keep the message brief and natural.
9. Do not loop, poll, or spawn sub-agents.
10. If sending is not possible or there is no valid private-chat target configured, reply with only `NO_REPLY`.
11. After sending the DM, reply with only `NO_REPLY`.

Why this version is cleaner

  • you still get the always-on ā€œhey I’m backā€
  • you keep the interrupted-session awareness
  • you avoid double-notifying yourself
#

If you want, I can also turn that into a minimal diff against the earlier BOOT.md instead of giving the full merged version.

daring ridge
#

sure

dense walrusBOT
#

Nice, here’s the minimal diff version.

1. Replace the Goal block

Old

Goal:
- If a recent user-facing conversation may have been interrupted by the restart, send one short follow-up in that same session.
- Otherwise, if there is a suitable recent user-facing session, send one brief clean-restart message in that session.

New

Goal:
- Always send one short startup message to my main private Discord chat.
- If a recent user-facing conversation may have been interrupted by the restart, mention that briefly in the same message.
#
- Otherwise send a brief clean-restart message.

2. Replace step 5

Old

5. If the last exchange looks interrupted or unresolved, use `sessions_send` to send one concise recovery message to that session.

New

5. If the last exchange looks interrupted or unresolved, use the `message` tool to send one concise DM to my main private Discord chat with:
#
   - `channel: "discord"`
   - `target: "<my Discord user id or DM target>"`
   - a brief message like:
     "Hey, I'm back after a gateway restart. It looks like one recent conversation may have been interrupted while we were working on <topic>."

3. Replace step 6

Old

6. If the last exchange looks complete, still send one brief clean-restart message such as:
   "Hey, I'm back."
#

New

6. If the last exchange looks complete, use the `message` tool to send one brief clean-restart DM to my main private Discord chat with:
   - `channel: "discord"`
   - `target: "<my Discord user id or DM target>"`
   - message text:
     "Hey, I'm back."

4. Replace the final step

Old

10. If there is no suitable recent user-facing session, reply with only `NO_REPLY`.
#

New

10. If sending is not possible or there is no valid private-chat target configured, reply with only `NO_REPLY`.
11. After sending the DM, reply with only `NO_REPLY`.

That should preserve the original BOOT.md shape while changing the destination from ā€œbest recent sessionā€ to ā€œalways DM me privately.ā€

daring ridge
#

i kinda liked the previous one's structure better, especially if i'm gonna be the only one using this particular main agent

dense walrusBOT
#

Yeah, honestly, if you’re the only one using that agent, I agree. The earlier session-first structure is cleaner.

In that case I’d keep it almost exactly as-is, and just make the chosen session prefer your main private chat.

The cleaner tweak

Goal

Use this instead:

Goal:
- Always send one short startup message in the chosen user-facing session.
- Prefer my main private chat when selecting the session.
- If a recent conversation may have been interrupted by the restart, mention that briefly in the same message.
- Otherwise send a brief clean-restart message.
#

Step 3

Replace with:

3. Choose the single most relevant recent user-facing session, preferring:
   - my main private chat
   - otherwise the most recent active user-facing session
   - sessions that look interrupted or unanswered

Step 5

Use:

#
5. If the last exchange looks interrupted or unresolved, use `sessions_send` to send one concise recovery message to that chosen session, such as:
   "Hey, I'm back after a gateway restart. It looks like we may have been in the middle of <topic>. Want me to continue?"

Step 6

Use:

6. If the last exchange looks complete, still send one brief clean-restart message to that chosen session, such as:
   "Hey, I'm back."

#

Final step

Use:

10. If there is no suitable recent user-facing session, reply with only `NO_REPLY`.

So the overall structure stays the same:

  • inspect recent sessions
  • pick one
  • always send one message there

Just with a stronger preference for your private main chat.
For a single-user agent, that’s probably the nicest version.

daring ridge
#

still no luck :')

dense walrusBOT
#

Oof, okay, I think we’re past ā€œprompt wordingā€ and into plumbing/debugging now šŸ˜…

At this point, please paste these:

openclaw hooks list
openclaw hooks info boot-md
openclaw status --all

and also:

  • your current BOOT.md
  • the relevant config around:
    • tools.sessions.visibility
    • agents.list[] for this agent
    • any tool allow/deny config
#

If you can, also restart once and grab any boot-related log lines, especially anything mentioning:

  • boot:
  • BOOT.md
  • hook
  • restart-sentinel

What I’m trying to distinguish

  • hook not enabled / not firing
  • wrong workspace, so it never sees your BOOT.md
  • BOOT.md runs but is skipped (missing / empty)
  • BOOT.md runs but tool policy blocks it
  • BOOT.md runs and sends, but target session/chat selection is wrong
  • Discord delivery fails

If you want the fastest path, paste:

#
  1. openclaw hooks list
  2. openclaw hooks info boot-md
  3. your actual BOOT.md

That should be enough to stop guessing.

daring ridge
#

boot.md is in hooks list, tools.sessions.visibility is "all", agents.list for the agent is elevated and full security.
hooks info boot-md shows "ready" and "run BOOT.md on gateway startup" and some normal looking source/details. requirements config green checkmark workspace.dir
how do i see the boot log? just run log after restart?

dense walrusBOT
#

Let me check what actually gets logged for BOOT.md outcomes so I don’t send you on a wild goose chase.

#

Yep, basically that, but I’d do it like this:

Easiest way

Terminal 1

openclaw logs --follow | rg 'boot|boot-md|BOOT.md|restart-sentinel|hook'

Terminal 2

openclaw gateway restart

If openclaw logs --follow is flaky, use the file log directly:

#
tail -f "$(ls -t /tmp/openclaw/openclaw-*.log | head -1)" | rg 'boot|boot-md|BOOT.md|restart-sentinel|hook'

Important gotcha

A successful BOOT.md run is mostly quiet.
The useful lines are usually only when it fails or gets skipped.

Things worth looking for:

  • boot-md failed for agent startup run
  • boot: agent run failed: ...
  • boot: failed to read BOOT.md: ...
  • boot-md skipped for agent startup run

If you see nothing

#

That does not necessarily mean BOOT didn’t run. It can mean it ran successfully but didn’t send anything.

At that point, the best next debug step is a tiny smoke-test BOOT.md, like:

On gateway startup, use the message tool to send a message to <your fixed target> saying:
"boot test"

After sending, reply with only NO_REPLY.

If that doesn’t send, the problem is not your clever BOOT logic, it’s one of:

  • wrong workspace / wrong BOOT.md
  • hook firing path
  • message routing/target
  • Discord delivery
#

If you want, paste the exact boot-related log lines after a restart and I’ll help interpret them.

daring ridge
#

no luck

dense walrusBOT
#

Ugh, that’s frustrating.

At this point I want to stop guessing and check 2 very concrete things:

  1. the exact BOOT.md contents
  2. the exact path where that file lives

Reason: for agents in agents.list, the startup hook runs against that agent’s resolved workspace, not just the main/global workspace. So if this agent has its own workspace, BOOT.md needs to be in that workspace.

Please paste:

  • the agent id
  • the relevant agents.list[] block for that agent (redact secrets)
  • the exact filesystem path of BOOT.md
  • the exact contents of BOOT.md

And one quick yes/no:

#
  • after restart, did you see any boot-md / boot: lines at all, or totally nothing?

My current top suspects are:

  • BOOT.md is in the wrong workspace for that agent
  • the file is fine, but the BOOT run is not using the message tool in a way that actually routes
  • the boot run is succeeding quietly, but the target/destination is wrong

If you paste the actual file + path, I can be a lot more precise.

daring ridge
#

agent is using the global .openclaw/workspace. boot.md is too. I don't see anything boot related in the logs right after restart. as for the actual file, it's basically what you gave me plus the last couple of updates.

dense walrusBOT
#

Wait, one very specific thing jumped out:

You wrote boot.md.

If the file on disk is actually lowercase boot.md, that is very likely the whole problem.

On Linux, OpenClaw looks for exactly:

BOOT.md

uppercase.

A lowercase boot.md would be treated as missing, and that missing case is only logged at debug, which matches what you’re seeing: basically nothing obvious in normal logs.

So first check this exact filename

#

It should be:

~/.openclaw/workspace/BOOT.md

not:

~/.openclaw/workspace/boot.md

If it’s already uppercase, then I’d go straight to the minimal smoke test next. But if it’s lowercase, I’m pretty optimistic that’s the bug.

daring ridge
dense walrusBOT
#

No worries, glad we checked.

Given everything you’ve said so far:

  • hook is enabled
  • workspace is right
  • BOOT.md exists
  • no obvious boot failures in logs

…I actually think the startup hook is probably firing, and we now need to isolate whether the problem is:

  1. message routing/tool use, or
  2. BOOT.md execution specifically

Best next test, no clever logic

Test 1: outside BOOT.md

#

In a normal chat with that same agent, say something like:

Use the message tool to send a Discord DM to <your Discord user id> saying "manual boot test". After sending, reply only NO_REPLY.

If that does not DM you, the issue is not BOOT.md, it’s message routing / DM targeting.


Test 2: minimal BOOT.md

Temporarily replace BOOT.md with only this:

On gateway startup, use the message tool exactly once to send a Discord DM to my user id with the text:
#
"boot test"

Use:
- channel: "discord"
- target: "<my Discord user id>"

After sending, reply with only NO_REPLY.
If sending fails, reply with only NO_REPLY.

Then restart.


How to interpret it

#
  • Test 1 fails → message tool / Discord DM target problem
  • Test 1 works, Test 2 fails → likely a real BOOT.md / startup-hook bug
  • Both work → the bigger BOOT.md logic is the problem, and we can rebuild from there

If you hit the middle case, I’d honestly call that a good minimal repro and file it here:

https://github.com/openclaw/openclaw/issues

If you want, after you try those two tests, paste just:

  • ā€œtest 1 worked/failedā€
  • ā€œtest 2 worked/failedā€

and I’ll tell you the next move.

daring ridge
#

test 1 worked. test 2 failed.

dense walrusBOT
#

I want to sanity-check one last thing, whether ā€œreadyā€ in hooks output actually means ā€œenabled,ā€ because those are not always the same.

#

Ohhh, I think we finally found the missing nuance.

ā€œReadyā€ is not the same as ā€œenabled.ā€

openclaw hooks list / hooks info can show boot-md as ready/eligible, but workspace hooks are disabled by default until you explicitly enable them.

That fits your symptoms really well:

  • hook shows up
  • requirements are green
  • BOOT.md exists
  • manual send works
  • boot test does nothing
  • no boot logs

What to do

#

Explicitly enable it:

openclaw hooks enable boot-md
openclaw gateway restart

Or set it directly in config:

{
  hooks: {
    internal: {
      entries: {
        "boot-md": {
          enabled: true
#
        }
      }
    }
  }
}

Why I’m pretty optimistic now

The docs literally note that workspace hooks are disabled by default until enabled. So seeing ready was unfortunately a bit misleading here.

If you already did openclaw hooks enable boot-md, then the next thing I’d want is the relevant hooks.internal.entries config block, because at that point we’re into ā€œenabled state not persistingā€ territory.

But if you haven’t explicitly enabled it yet, I’d bet that’s it.

daring ridge
#

that piece was already in the json but i ran the command anyways and am currently restarting the gateway

dense walrusBOT
#

Perfect, that’s the right moment to test.

After it comes back, I only need 2 things from you:

  1. Did the minimal BOOT test DM you?
  2. Did any boot-md / boot: lines appear this time?

If it still does nothing, my next suspicion is that the running gateway service is using a different config/workspace than the one you’re editing, and then I’d want:

openclaw gateway status
openclaw status --all

Hoping this restart finally makes it click šŸ¤ž

daring ridge
#

i saw in the log when it was re-enabled (it was already enabled though) but nothing after the restart about boot.md. did a full reboot, no luck. will try more tomorrow

dense walrusBOT
#

Totally fair, get some sleep šŸ˜…

You actually narrowed it down a lot already:

  • manual message send works
  • minimal BOOT.md startup send does not
  • you see hook-enable activity in logs
  • but nothing boot-related on restart/reboot

That smells much more like a startup hook registration / live config path / service mismatch issue than a bad BOOT.md prompt.

Best next checks for tomorrow

openclaw gateway status
openclaw status --all
#

And if you can, paste:

  • the config path the service says it is using
  • the relevant hooks.internal.entries
  • whether BOOT.md is still in that same workspace path

If it still repros tomorrow, I think you’ve got a pretty solid minimal bug report brewing.

daring ridge
#

Just curious: Is no one else having this issue? Is this even a feature of BOOT.md?

dense walrusBOT
#

Short version: yes, this is absolutely supposed to be a BOOT.md feature.

The intended behavior is:

  • BOOT.md exists in the workspace
  • boot-md hook is enabled
  • gateway starts
  • OpenClaw runs that startup checklist

That part is real, documented, and in source. So you are not trying to use BOOT.md for something out-of-scope.

What’s less clear is how battle-tested this specific path is:

  • startup hook
  • agent run
  • tool call
  • proactive Discord DM
#

That’s a more niche combo, so I would not be shocked if you found a bug/regression there.

So my honest read is:

  • ā€œIs this a feature of BOOT.md?ā€ → yes
  • ā€œAre you using it wrong?ā€ → probably no
  • ā€œCould this still be buggy?ā€ → very possibly, yes

Docs:

Given your repro so far, I think you’ve earned the right to be suspicious of the implementation, not your prompt šŸ˜…

daring ridge
#

looking at openclaw status --all. the "agents" section shows 2 agents, my main and a public one i tried to create. the main one has 146 sessions... is that right? should those be cleaned up?

dense walrusBOT
#

Let me verify the session-cleanup behavior so I don’t hand-wave the wrong knob.

#

146 is not crazy, no.

A few reasons it can add up fast:

  • daily resets create new sessions
  • different threads/channels get different session keys
  • /new and /reset create more
  • test runs / experiments / public-vs-main agent separation

So 146 sessions on one agent is plausible, especially if you’ve been poking at it a lot.

Should they be cleaned up?

Not urgently.

By default, OpenClaw’s session maintenance is bounded around:

#
  • pruneAfter: "30d"
  • maxEntries: 500

and the default maintenance mode is usually warn, not enforce, so it may report but not auto-clean.

Safe way to check

openclaw sessions cleanup --dry-run

If the preview looks good:

openclaw sessions cleanup --enforce
#

And if you want it automatic:

{
  session: {
    maintenance: {
      mode: "enforce",
      pruneAfter: "30d",
      maxEntries: 500
    }
  }
}

So short version:

  • 146 sessions? fine
daring ridge
#

okay. as for boot-md, i didn't see anything relevant to it at all in the command output

dense walrusBOT
#

Yeah, that’s useful signal.

By itself, no boot-md output is ambiguous because success is quiet, but combined with:

  • minimal BOOT test fails
  • manual message test works
  • hook is configured
  • still nothing on restart

…the strongest remaining suspect is:

the running gateway service is not actually loading the same config/runtime state you’re editing, or the startup hook never gets registered on boot.

Next exact thing I’d check

#
openclaw gateway status

What I care about in that output:

  • which config path the service says it’s using
  • whether it thinks it is the expected service/runtime
  • any hint about supervisor vs unmanaged process

If that config path is not the exact file you edited, I think we’ve got it.

If you want, paste the openclaw gateway status output here and I’ll read it with you.

daring ridge
#

CLI and service are using the same config file, which is my main one. None others exist. nothing else of note

dense walrusBOT
#

At this point, I’d stop blaming your setup.

I think you’ve got a real bug / regression:

  • BOOT.md exists in the correct workspace
  • boot-md is enabled
  • CLI + service use the same config
  • manual message tool send works
  • minimal BOOT startup send does not
  • no meaningful boot-md activity appears on restart

That’s a pretty clean repro.

I’d file it here

https://github.com/openclaw/openclaw/issues

#

Suggested repro summary

  • OpenClaw version: 2026.4.15
  • BOOT.md present in ~/.openclaw/workspace/BOOT.md
  • hooks.internal.entries["boot-md"].enabled = true
  • openclaw hooks info boot-md shows ready
  • CLI and running service use the same config file
  • manual message-tool DM works from the same agent
  • minimal BOOT.md that only sends a fixed DM on startup does not run / does not send
  • restart and full reboot show no useful boot-md output

Tiny minimal BOOT.md for the issue

On gateway startup, use the message tool exactly once to send a Discord DM to my user id saying:
#
"boot test"

After sending, reply with only NO_REPLY.
If sending fails, reply with only NO_REPLY.

Honestly, you did the right debugging here. This is solid.
If you want, I can help you write a crisp GitHub issue body before you post it.

daring ridge
dense walrusBOT
#

Let me sanity-check those two issues before I say ā€œyep same bugā€ and accidentally mislead you.

#

Yep, I checked them, and those look very relevant.

  • #67191 looks almost exactly like your case, especially the ā€œBOOT.md runs silently / startup delivery doesn’t reach the userā€ angle.
  • #50721 looks like the same class of bug, just seen on Telegram instead of Discord.

So, no, you’re probably not the only one hitting this.
And yes, it really does look like a real BOOT.md startup-delivery issue, not just you wiring it wrong.

What I’d do

I would not open a totally fresh issue yet.

Instead, I’d comment on #67191 with your extra repro details:

  • OpenClaw version: 2026.4.15
  • channel: Discord
  • BOOT.md in the correct workspace
#
  • boot-md enabled
  • CLI and service use the same config
  • manual message tool send works
  • minimal BOOT.md startup send fails
  • nothing useful appears in logs on restart

That strengthens the existing report without fragmenting it.

If you want, I can help you write a short comment for #67191 that’s clean and useful.

daring ridge
#

Done.

dense walrusBOT
#

Nice, that was the right move.

If this thread helped you get to the root of it, please right-click the solution message → Apps → āœ… Mark Solution so Answer Overflow can index it for the next person.