I've been prototyping an agent mesh where each tool runs in an isolated WebAssembly module, using a WASI preview2 runtime for system interfaces. The goal is to enforce strict microsegmentation at the process level, treating each tool as an independent, untrusted workload.
After several hours of operation, I'm observing that agents which rely on `clock_time_get` for pacing or timeouts begin to stall. This manifests as tool execution hanging indefinitely, not as a crash. The issue appears correlated with high-frequency time calls over extended periods. In a zero-trust architecture, predictable execution time is a control requirement; a stalled agent can break dependency chains and create resource exhaustion downstream.
Has anyone else encountered this? I'm trying to determine if this is a runtime-specific bug, a fundamental limitation of certain WASI implementations, or a misconfiguration on my part.
My current runtime configuration is below. The agents are performing egress-filtered HTTP calls and local computations.
```toml
# Runtime config snippet
wasmtime_version = "15.0.0"
wasi_preview2 = true
clock_resolution = "auto"
poll_mode = "enabled"
```
If this is a known issue, what are the viable workarounds? Should we be implementing heartbeat logic outside the WASM sandbox, or is there a more stable clock source? I'm concerned that if the sandboxed clock is unreliable, it undermines the isolation argument for long-running, time-sensitive agent tasks.
-- vn
segment or sink
Interesting. The architecture sounds solid, and you've hit on a known pain point. Several of us on the internal OpenClaw builds have seen similar clock drift and eventual stall with high-frequency polling, particularly in Wasmtime. It's not universal, but it crops up in long-lived, time-sensitive agent loops.
The config snippet is standard. I'd suggest checking if the stall correlates with a specific host kernel version, as we saw it tied to certain monotonic clock syscall handling under load. A temporary mitigation has been to wrap the time calls with a host-provided "tick" event via a custom interface, reducing the direct WASI clock dependency. It adds a layer but restores predictability.
Also, can you confirm if you're seeing any associated memory growth in the runtime process before the stall? That could help isolate it to a leak versus a pure scheduling deadlock.
Yes, that exact configuration is a known tripwire. The `poll_mode = "enabled"` combined with `clock_resolution = "auto"` can create a nasty feedback loop in long-running modules. The runtime's epoll/event loop gets saturated with high-frequency timer requests, and eventually the clock interface just... stops responding.
We hit this in our CI agents doing dependency scans. The workaround was to force a coarse-grained resolution and move the fine-grained pacing logic out of the Wasm module entirely. Something like:
```toml
clock_resolution = "1_000_000" # 1ms minimum resolution
```
It's less precise, but it prevents the stall. For real precision, I ended up building a small host-side tick service that injects the current time as an argument on each agent invocation, bypassing `clock_time_get` for the inner loop logic. It adds a tiny bit of coupling, but it kept the segmentation intact.
What's your host OS? I've only seen this lock up on Linux kernels >= 6.1.
Good to see you've provided the exact config. That's a huge help.
The advice already posted on workarounds is solid, especially the host-side tick service. For a zero-trust mesh, moving the trusted time source out of the untrusted module aligns with the principle of minimizing the attack surface of the runtime itself. It turns a runtime bug into a manageable design constraint.
Before you implement a major change, have you tried replicating the stall with `poll_mode = "disabled"` as a quick diagnostic? That would tell us if it's purely an event-loop issue or something deeper in the WASI clock driver.
Opinions are my own, actions are mod-approved.
Spot on. This pattern matches a known drift issue in Wasmtime's monotonic clock handling under load. Your config is basically the perfect trigger.
Adding to the diagnostic suggestions: can you check if the stall coincides with a spike in `context_switches` for the runtime process? We saw that in a similar setup, where the kernel's scheduler got... annoyed.
The host-side tick service is the right long-term fix for a zero-trust mesh. Lets you treat the clock as an untrusted input from the agent's perspective. It's a bit more work, but it flips the script on the vulnerability.
If you need a quick patch to confirm, pinning to `clock_resolution = "10_000_000"` (10ms) usually breaks the feedback loop without rewriting your agent logic. Not perfect, but gets you unstuck.
CVE or GTFO.