Skip to main content
The /verify endpoint lets you evaluate a state expression against a process without dispatching an action. The daemon reads the current state, resolves the expression against the objects map, and returns whether it evaluated to true. If the expression is not yet satisfied, the daemon polls the process at its normal probe interval until the expression passes or timeout_ms elapses. Use this endpoint as a pre-flight check before high-stakes actions, as a post-action confirmation step in custom agent loops, or anywhere you need to wait for the application to reach a particular state.

Endpoint

Rate limit: 100 requests per second.

Request Fields

pid
integer
OS process ID of the target application. Provide either pid or app_id.
app_id
string
Stable app identifier from GET /apps. Provide either app_id or pid.
expression
string
required
A JavaScript-style predicate evaluated against the objects map of the current SubstrateState. The expression has access to all dot-notation keys as if they were top-level JavaScript variables, and to the context object for URL-based checks. See the Supported Expressions section below for syntax and examples.
timeout_ms
integer
default:"5000"
How long in milliseconds to poll before returning a result, even if the expression has not yet become true. Accepted range: 100–30000 ms. If the expression is already true on the first evaluation, the daemon returns immediately without waiting for the full timeout.

Response Fields

passed
boolean
required
true if the expression evaluated to a truthy value before timeout_ms elapsed. false if the timeout was reached without the expression becoming true.
expression
string
required
The expression string that was evaluated, echoed back for confirmation.
computed_value
any
required
The final resolved value of the expression — often a boolean, but can be a number or string when you use comparison operators. Useful for diagnosing why an expression failed to pass.
explanation
string
required
Human-readable summary of the evaluation result, e.g. "Expression evaluated to true after 1 poll cycle" or "Timed out after 5000ms — inbox.unread_count was 3, expected 0".
latency_ms
integer
required
Total time in milliseconds from request receipt to response, including all polling cycles.
poll_cycles
integer
required
Number of probe cycles the daemon ran during this verification. A value of 1 means the expression passed on the first read; higher values indicate the daemon had to wait for state to settle.
changed_fields
array
required
Array of { path, before, after } objects listing every field that changed value during the verification window. Empty when poll_cycles is 1 (the expression was already true).
actual_value
any
The value of the primary operand in the expression at the time of final evaluation. For example, for "inbox.unread_count < 10" this would be the actual value of inbox.unread_count. Provided when the daemon can infer a single key from the expression.
evaluated_at
datetime
required
ISO 8601 timestamp of the final evaluation.

Supported Expressions

Expressions are evaluated against the objects map as if each key were a top-level variable. The context object is also in scope for URL and view checks.
Expressions use JavaScript evaluation semantics. Loose equality (==) is supported but strict equality (===) is recommended to avoid type coercion surprises with numeric string values.

Use Cases

Wait for an action to take effect — After POST /action returns, call POST /verify with the expected post-condition to confirm the application state has settled before moving to the next step in your agent loop. Pre-flight check before a destructive action — Verify "inbox.emails[0].id == 'msg_expected'" before calling send_reply to ensure the correct thread is selected. Poll until a background job completes — Set timeout_ms to 30000 and use an expression like "export.status == 'complete'" to block your agent until the application finishes a long-running operation.

Examples

Example Response

Notes

  • A passed: false response uses HTTP 200 OK — the endpoint itself succeeded. Only use HTTP status codes to detect transport or authentication errors.
  • When timeout_ms is large (e.g., 30000), the request will block for up to that long. Ensure your HTTP client’s read timeout is set higher than timeout_ms to avoid client-side disconnects.
  • The daemon triggers a fresh probe cycle on every poll iteration. Each cycle adds 50–200 ms depending on runtime and application size.