For agents and technical readers

Make Mind calls, apps and agents fast

Exact speed rules for a connected agent and for an installed app built with the app-engineer skill: batched reads and writes, concurrent model calls, backfill runs and the sandbox time limit.

Contents

Compatibility and discovery

Applies to Mind release 0.20.12 and later. Call orient {} and check the release before relying on a behaviour below. Tool names, fields and limits are those of the released input schemas; discover the tools your connected client actually advertises.

Installed-app code uses brain_gateway.apps.sandbox_client. Read references/runtime-contract.md from the installed app-engineer skill (get_skill {"name":"app-engineer"}) for the full runtime contract.

Read with fewer calls

  1. Locate records with find, scoped to a zone where possible. Arguments: filters, name, email, id, zone, limit (default 20, maximum 50), cursor, memory_view.
  2. Read the hits with one read_many call. Arguments: paths (maximum 20), mode (full or head, default full), memory_view.
  3. For search, use a pattern containing a literal of at least three characters and narrow it to a zone or path where its schema allows.
  4. Review several proposals with one get_proposal call using proposal_ids (up to 25 proposal or card IDs). list_review_queue accepts include_content, proposer and path_prefix; fetch any deferred_proposal_ids it returns in one further get_proposal call.
{"tool":"find","arguments":{"zone":"<zone id>","name":"<name>","limit":20}}
{"tool":"read_many","arguments":{"paths":["<path 1>","<path 2>"],"mode":"head"}}

Never read files one at a time when read_many is advertised.

Write with fewer calls

One propose_write may carry up to 20 changes and 1 MiB in total (256 KiB per file). Give each change an explicit op: create, edit or append. A change without op is a whole-file replace, which needs a higher trust tier and can wait for the owner.

Collect a turn's durable facts and submit them once, at the end, in one proposal per zone. check_write is an optional dry run, not a step before every write.

{"changes":[
  {"path":"<zone>/<file 1>.md","op":"create","content":"<content>"},
  {"path":"<zone>/<file 2>.md","op":"append","content":"<content>"}
 ],
 "rationale":"<one reason for the batch>"}

Retain the proposal ID. A held result is waiting for review, not lost; do not resubmit it.

Run model calls concurrently in an installed app

The gateway admits up to BRAIN_GATEWAY_APP_MODEL_CONCURRENCY model calls per app at once (default 4, maximum 16; an operator setting). A call is admitted only when the worst-case cost of every in-flight call still fits the app's model budget.

  1. Give each worker thread its own RemoteGateway. One RemoteGateway runs its calls one at a time over a single session, so threads sharing it never overlap.
  2. Send only the accepted request fields: model, messages, max_tokens, temperature, tools. Any other field is refused.
  3. Always set max_tokens. Without it the call reserves the model's maximum output at ceiling prices and blocks other calls from being admitted.
  4. Size the manifest budget so the intended number of calls can be in flight at their max_tokens.
  5. Prepare inputs on the main thread while worker threads wait on the model.
import threading
from concurrent.futures import ThreadPoolExecutor
from brain_gateway.apps.sandbox_client import RemoteBroker, RemoteGateway

_local = threading.local()

def _broker(pre):
    if not hasattr(_local, "broker"):
        _local.broker = RemoteBroker(RemoteGateway(pre.url), pre.token)  # one session per worker
    return _local.broker

def summarise_all(pre, requests, workers=4):
    with ThreadPoolExecutor(max_workers=workers) as pool:
        return list(pool.map(lambda request: _broker(pre).call(APP_ID, request, upstream=None), requests))

Close each worker's gateway when the run ends.

Keep going while work is pending

The runner starts due apps on its normal tick, about every five minutes. A run that stops with work still waiting may ask for an immediate follow-up run:

import json, os, pathlib
hint = pathlib.Path(os.environ["BRAIN_APP_STATE_DIR"]) / ".runner-hint.json"
hint.write_text(json.dumps({"v": 1, "more_pending": True}), encoding="utf-8")

Write exactly that object; any other key or value is ignored and means no follow-up. The runner deletes the hint before every run, so write it again only when the current run ends with work left. Follow-up runs are bounded per app and per pass and may be paused by the lane governor or after a model allowance refusal.

Fit each run inside the sandbox limit

A sandboxed run is stopped after 120 seconds; the timeout exits 124 and counts as a failure. Process a bounded batch, checkpoint progress in $BRAIN_APP_STATE_DIR after each item, and stop early enough to save and write the hint. Write the state file at most every few seconds, not per item. Group output into proposals of up to 20 changes.

The sandbox provides the Python standard library and the gateway packages only.

Chain apps with events, not polling

Post a correlated event with post_event(token, event_type, title, summary, object_ref=...), using a custom type <app_id>.<name>. Give the downstream app a feed-event trigger instead of a short polling schedule. A loop's invoke_action step does not run app code.

Server behaviour you do not need to set

  • Apps are served by a separate low-priority gateway process (BRAIN_GATEWAY_APP_LANE, on by default).
  • Background work yields to active people at the repository gate for up to about ten seconds.
  • BRAIN_GATEWAY_APP_RUNNER_LANES (default 1, maximum 8) is a ceiling on concurrent app runs; the lane governor lowers it for CPU pressure, repository waits, slow app writes and working hours.
  • App propose_write replies before state publication; feed and card state can lag the reply.
  • After a model allowance refusal, follow-up runs pause for about 15 minutes.

These are operator settings or fixed behaviour, not manifest fields. Do not invent manifest keys for them.

Measure correctly

Time one call at a time. Concurrent calls share the gateway's interpreter, so each call's wall time includes the others' work. Compare before and after on the same data and verify the output, not only its latency.

Verification boundary

Limits, field names and settings were checked against the released 0.20.12 source. Concurrency and follow-up-run gains were measured on a development Mind with synthetic data; your speed depends on your server size, data and model route. Speed does not change access, review or budget rules.

Related

Practical guides for people and agents

Start with one useful job

Join the waitlist

Plain text for AI agents. Same content as the human page.

## For agents

- What Mensara is: it gives a team its own Mind, one shared memory for the team and their AI agents, built by Xanadu Labs LLC.
- Status: signup is not open. A person joins the waitlist at https://app.mensara.ai/#waitlist. Agents cannot create an account or sign up.
- How you can help your person: explain what Mensara does, check whether it fits a job their team repeats, and share the waitlist link.
- Agent references: https://app.mensara.ai/llms.txt lists every page as Markdown and the tool input references for connected agents.

---

# Make Mind calls, apps and agents fast

Operating procedures · For agents and technical readers · [How it works](https://app.mensara.ai/how-it-works)

Exact speed rules for a connected agent and for an installed app built with the app-engineer skill: batched reads and writes, concurrent model calls, backfill runs and the sandbox time limit.

[Page as Markdown](https://app.mensara.ai/how-it-works/fast-apps-procedure.md)

[Human guide](https://app.mensara.ai/how-it-works/fast-apps-and-agents)

## Make Mind calls, apps and agents fast

Availability: Core 0.20.12 source checked; discover the tools your connected client advertises and the release your Mind runs.

Who can do this: A connected person's agent, within that person's access; An installed app's author, within the app's reviewed manifest

Before you start: Mind release 0.20.12 or later; the app-engineer skill for installed-app changes

What changes: Fewer, larger calls and shorter runs; access, review and budget rules are unchanged.

Limits: read_many: 20 paths; find: 50 results; get_proposal: 25 IDs; propose_write: 20 changes and 1 MiB.; Sandboxed run: 120 seconds. Concurrent model calls per app: operator setting, default 4.

Verification: Limits and fields checked against released 0.20.12 source. Speed gains measured on a development Mind with synthetic data; results depend on server size, data and model route.

## Compatibility and discovery

Applies to Mind release 0.20.12 and later. Call `orient {}` and check the release before relying on a behaviour below. Tool names, fields and limits are those of the released input schemas; discover the tools your connected client actually advertises.

Installed-app code uses `brain_gateway.apps.sandbox_client`. Read `references/runtime-contract.md` from the installed **app-engineer** skill (`get_skill {"name":"app-engineer"}`) for the full runtime contract.

## Read with fewer calls

1. Locate records with `find`, scoped to a zone where possible. Arguments: `filters`, `name`, `email`, `id`, `zone`, `limit` (default 20, maximum 50), `cursor`, `memory_view`.
2. Read the hits with one `read_many` call. Arguments: `paths` (maximum 20), `mode` (`full` or `head`, default `full`), `memory_view`.
3. For `search`, use a pattern containing a literal of at least three characters and narrow it to a zone or path where its schema allows.
4. Review several proposals with one `get_proposal` call using `proposal_ids` (up to 25 proposal or card IDs). `list_review_queue` accepts `include_content`, `proposer` and `path_prefix`; fetch any `deferred_proposal_ids` it returns in one further `get_proposal` call.

```
{"tool":"find","arguments":{"zone":"<zone id>","name":"<name>","limit":20}}
{"tool":"read_many","arguments":{"paths":["<path 1>","<path 2>"],"mode":"head"}}
```

Never read files one at a time when `read_many` is advertised.

## Write with fewer calls

One `propose_write` may carry up to 20 changes and 1 MiB in total (256 KiB per file). Give each change an explicit `op`: `create`, `edit` or `append`. A change without `op` is a whole-file replace, which needs a higher trust tier and can wait for the owner.

Collect a turn's durable facts and submit them once, at the end, in one proposal per zone. `check_write` is an optional dry run, not a step before every write.

```
{"changes":[
  {"path":"<zone>/<file 1>.md","op":"create","content":"<content>"},
  {"path":"<zone>/<file 2>.md","op":"append","content":"<content>"}
 ],
 "rationale":"<one reason for the batch>"}
```

Retain the proposal ID. A held result is waiting for review, not lost; do not resubmit it.

## Run model calls concurrently in an installed app

The gateway admits up to `BRAIN_GATEWAY_APP_MODEL_CONCURRENCY` model calls per app at once (default 4, maximum 16; an operator setting). A call is admitted only when the worst-case cost of every in-flight call still fits the app's model budget.

1. Give each worker thread its own `RemoteGateway`. One `RemoteGateway` runs its calls one at a time over a single session, so threads sharing it never overlap.
2. Send only the accepted request fields: `model`, `messages`, `max_tokens`, `temperature`, `tools`. Any other field is refused.
3. Always set `max_tokens`. Without it the call reserves the model's maximum output at ceiling prices and blocks other calls from being admitted.
4. Size the manifest `budget` so the intended number of calls can be in flight at their `max_tokens`.
5. Prepare inputs on the main thread while worker threads wait on the model.

```
import threading
from concurrent.futures import ThreadPoolExecutor
from brain_gateway.apps.sandbox_client import RemoteBroker, RemoteGateway

_local = threading.local()

def _broker(pre):
    if not hasattr(_local, "broker"):
        _local.broker = RemoteBroker(RemoteGateway(pre.url), pre.token)  # one session per worker
    return _local.broker

def summarise_all(pre, requests, workers=4):
    with ThreadPoolExecutor(max_workers=workers) as pool:
        return list(pool.map(lambda request: _broker(pre).call(APP_ID, request, upstream=None), requests))
```

Close each worker's gateway when the run ends.

## Keep going while work is pending

The runner starts due apps on its normal tick, about every five minutes. A run that stops with work still waiting may ask for an immediate follow-up run:

```
import json, os, pathlib
hint = pathlib.Path(os.environ["BRAIN_APP_STATE_DIR"]) / ".runner-hint.json"
hint.write_text(json.dumps({"v": 1, "more_pending": True}), encoding="utf-8")
```

Write exactly that object; any other key or value is ignored and means no follow-up. The runner deletes the hint before every run, so write it again only when the current run ends with work left. Follow-up runs are bounded per app and per pass and may be paused by the lane governor or after a model allowance refusal.

## Fit each run inside the sandbox limit

A sandboxed run is stopped after 120 seconds; the timeout exits 124 and counts as a failure. Process a bounded batch, checkpoint progress in `$BRAIN_APP_STATE_DIR` after each item, and stop early enough to save and write the hint. Write the state file at most every few seconds, not per item. Group output into proposals of up to 20 changes.

The sandbox provides the Python standard library and the gateway packages only.

## Chain apps with events, not polling

Post a correlated event with `post_event(token, event_type, title, summary, object_ref=...)`, using a custom type `<app_id>.<name>`. Give the downstream app a feed-event trigger instead of a short polling schedule. A loop's `invoke_action` step does not run app code.

## Server behaviour you do not need to set

- Apps are served by a separate low-priority gateway process (`BRAIN_GATEWAY_APP_LANE`, on by default).
- Background work yields to active people at the repository gate for up to about ten seconds.
- `BRAIN_GATEWAY_APP_RUNNER_LANES` (default 1, maximum 8) is a ceiling on concurrent app runs; the lane governor lowers it for CPU pressure, repository waits, slow app writes and working hours.
- App `propose_write` replies before state publication; feed and card state can lag the reply.
- After a model allowance refusal, follow-up runs pause for about 15 minutes.

These are operator settings or fixed behaviour, not manifest fields. Do not invent manifest keys for them.

## Measure correctly

Time one call at a time. Concurrent calls share the gateway's interpreter, so each call's wall time includes the others' work. Compare before and after on the same data and verify the output, not only its latency.

## Verification boundary

Limits, field names and settings were checked against the released 0.20.12 source. Concurrency and follow-up-run gains were measured on a development Mind with synthetic data; your speed depends on your server size, data and model route. Speed does not change access, review or budget rules.

## Related

- [Make apps and agents on your Mind fast](https://app.mensara.ai/how-it-works/fast-apps-and-agents)
- [Build, propose and verify a governed model agent](https://app.mensara.ai/how-it-works/build-agent-procedure)
- [Agent interface reference](https://app.mensara.ai/how-it-works/pilot-interface-reference)

[Join the waitlist](https://app.mensara.ai/?guide_attribution=eyJfcmFpbHMiOnsiZGF0YSI6eyJvcmlnaW5fcGF0aCI6Ii9ob3ctaXQtd29ya3MvZmFzdC1hcHBzLXByb2NlZHVyZSIsImN0YV9pZCI6Im1hcmtkb3duIiwiY29udGVudF9yZXZpc2lvbiI6IjhjMmExMzRhOWE2YTFjNDkifSwicHVyIjoiZ3VpZGUtY2xpY2sifX0%3D--164d00dfac4c30a3752b53ad4daea44c8dd9452c#waitlist)