Limits and safeguards¶
Look up exact limits for a skipped file, a partial reply or a stopped program. For recovery steps, start with Troubleshooting; for what to review before collecting or sharing, see Privacy.
Size bounds¶
| Resource | Limit |
|---|---|
bf.yaml, machine registry, eval suite |
1 MiB each |
| YAML structure, including frontmatter | 32 nesting levels and 20,000 parser events; integers up to 4,300 decimal digits in any base |
| Authored note | 4 MiB |
| Note or record title | 4,096 characters; listings show 200, then … |
Note aliases, links, tags |
1,000 each |
Note alias, links or sources entry, entity, resource |
8,192 characters each |
| Search or page reply | Items end early near 32 KiB and continue at next_offset; home lists as many projects as fit the reply as printed, with projects_total |
| Any search or read reply | 4 MiB; a larger one fails with response exceeds its byte limit; narrow the request |
| Exact read | Text pages near 32 KiB; the first page adds all other fields, such as attributes |
| Paged note divided by headings | Opens with 4 KiB of text; its outline lists up to 200 sections |
| Backlink previews | 5 newest items per relation, excerpts of 160 characters; 64 relation groups, then backlinks_omitted |
| Source folder settle time | 5 seconds: a memories/SOURCE folder changed more recently is listed again at each search or read |
| Claims of a subject | 20 per relation and 50 in all |
| Record file | 16 MiB |
Record fields other than text |
2 MiB as UTF-8 JSON, so an exact read's first page stays within the reply limit |
| Record id | 1–4,096 characters and 7,988 once percent-encoded |
| Record text | 4,194,304 characters; longer text fails the run unless the sensor sets truncate_text or max_text_bytes |
| Record links, aliases, field names | 1,000 each |
| Record URL, link, field value | 8,192 characters |
| Listed field value | 200 characters; longer values stay in the exact read |
| Listed fields of one item | 2 KiB of JSON, in field-name order; later fields stay in the exact read |
| Entries per record source or authored folder | 100,000 |
| Folder depth | 64 levels below a scanned folder; a deeper folder fails the scan and names it |
| Note path | 7,988 characters once percent-encoded |
| Search query | 4,096 characters; the first 32 distinct words match |
| Search results per page | 50 |
| Page sizes | Folders and tags 200; memories/SOURCE 20; other pages 50 |
| Offsets | 2^53−1 |
| Skipped files per brain | 200 listed in problems, each error cut to 1 KiB with …, then a count |
| Validation problems, warnings, unresolved targets | 200 each, then a *_truncated flag; 20 spellings per warning |
| Reasons named by one diagnostic | The first 5 distinct reasons, then and N more |
| Broken link named by a routine's error | The first one, cut to 200 characters with …, then and N more |
Relation targets |
64 prefixes of at most 1,024 characters |
| Retrieval suites | 100 suites per run, 200 cases per suite |
| Records changed by one collection | 99,999; narrow the window or split the source |
| Reprojection | 1,000 changed records per transaction; 200 failed records listed, then "problems_truncated":true |
| Sensor output | 64 MiB by default, up to 256 MiB |
| Action routine output | 1 MiB by default, up to 4 MiB; a log routine's output only feeds its log |
Routine or assistant input from bf run |
1 MiB, ending within 10 seconds when piped |
| Assistant output | 1 MiB by default, up to 4 MiB |
| Prompt file, expanded prompt | 120,000 bytes each, as an argument or on standard input; below Linux's 128 KiB bound on one argument |
| Program name | 64 characters |
| Program command | The program and up to 127 arguments of at most 16,384 characters each |
Routine hooks |
16 events |
Program and channel timeout |
1–3,600 seconds |
refresh, lookback, overlap, reconcile, silent_after |
up to 365 days |
expire_after |
1 hour to 100 years |
memories/SOURCE/.forgotten |
8 MiB, about 120,000 forgotten records per source |
keep |
1–10,000 routine actions; 1–50,000 assistant records |
| Program log | 1 MiB per logs/NAME.log; per run, the last 256 KiB of stderr and of a log routine's stdout |
Folder entries:
- Each record takes one folder entry.
bf statuswarns above 80,000 entries without failing--check.- A tree over the limit fails the scan and names the folder.
- Split a crowded source's sensor or archive its older records.
- Keep bulky imports in the brain's root
inputs/ororiginals/, which are not scanned.
A long pasted question matches only its first 32 distinct words after function words are dropped: keep the distinctive terms.
Page sizes bound one reply, not the result: follow next_offset. SQLite still ranks every match up to a deep offset, so very deep pages take longer.
Processes and logs¶
Sensors, routines and assistants run from the brain folder with direct arguments, without a shell.
- Their standard input is
/dev/null, with two exceptions: what a hook orbf run --stdinpipes to a routine, and the expanded prompt of an assistant command without{{prompt}}. - They receive
BF_BRAINset to that brain, so a nestedbfcall reads the brain running it.
BF removes environment variables that could load code before your program starts, such as BASH_ENV or PYTHONPATH:
| Removed | Reason |
|---|---|
LD_*, DYLD_*, GCONV_PATH |
Can inject loader libraries or conversion modules. |
BASH_ENV, ENV, BASH_FUNC_*, SHELLOPTS, BASHOPTS, PS4, ZDOTDIR |
Can supply shell startup code, options or functions. |
PYTHON*, Java, Node, Ruby, Perl and PHP startup options, DOTNET_STARTUP_HOOKS, CORECLR_*, R_PROFILE*, R_ENVIRON*, LUA_INIT*, LUA_PATH*, LUA_CPATH* |
Can alter interpreter startup or module loading. |
Relative or empty PATH entries |
Could run an unexpected program from the brain folder. |
Other variables, including provider credentials and absolute PATH entries, remain. The list is best effort, not a sandbox.
- When a program needs dependencies, use an explicit runtime such as
uv run --no-project sensors/example.py. - A program that needs one of these variables sets it in its own command, such as
[env, R_ENVIRON_USER=/path/to/Renviron, Rscript, sensors/example.R].
How a run ends:
- A run ends when the program exits and its standard output closes.
- When a run ends, successful or not, BF kills the program's whole process group. Background helpers end with it unless they leave that group, as daemons that start their own session do.
- A timeout, cancellation or closed terminal ends a run early, as does output beyond
max_bytesfrom a sensor or action routine. Partial output never replaces stored records. - Cancellation during startup waits until BF owns the new process, then kills its group too.
- A program that another process kills, such as the out-of-memory killer, fails naming the signal:
program was killed by SIGKILL. - A background helper that keeps standard output open more than a second after the exit fails the run. Redirecting its output, for example to
/dev/null, avoids that failure, not the kill. - A helper holding only stderr never delays or fails the run.
- Watch, and the service files in Run watch as a service, allow at least 60 seconds after a stop request, so an interrupted record write can roll back.
Each run appends entries to the program's logs/NAME.log in the brain:
- a
== TIME OUTCOME ==heading when the program exits; - its stderr and a log routine's stdout;
- another heading with the run's result, such as the records collected or the failure.
Log rules:
- The log keeps its newest whole entries within 1 MiB.
- Errors and run history name the log without quoting provider output.
bf initignoreslogs/in Git, and search never reads it.- A log can still hold provider output: keep it private and never paste it into a public issue.
Search and read keep a local usage.jsonl:
- Each event holds the time, operation, kind and result count, plus, on zero-result searches, up to 8 unmatched tokens of at most 64 characters each.
- A search's kind names its scope:
none,period,folder,note,memories,source,source-period,record,identity,tag, orcombinedfor a period with another scope. A source with a period, written either way, counts assource-period. - A read's kind names its page:
home,period,tasks,tags,tag,memories,source,source-period,record,folder,note,section,action,identityorrelation. - It never holds query text, refs, paths or identities.
- Beyond 1 MiB, BF sums each earlier UTC day into one line, with up to 32 unmatched tokens, and drops days older than 30. Today's events stay as they are unless they alone pass 768 KiB.
bf statussummarizes today with the 6 or 29 UTC days before it. Events written before kinds existed count in the totals only, and a cut made by an older release still marks the windows it shortened withsince.
Assistants, channels and the queue:
| Resource | Limit |
|---|---|
| Assistant inputs, schedules | 32 entries each |
| Assistants per brain | 32 |
| Channels per brain | 64 |
| Channel read | 1,000 messages; a read input catches up on a longer window in parts, at most 16 admitted parts per poll |
| Stream frame | 1 MiB by default (1 KiB–1 MiB) |
| Stream lifetime | No deadline for a healthy idle stream; each stream run ends with one timed entry in logs/channel.NAME.stream.log |
| Queue database | 256 MiB |
| Queue admission | New work until the queue holds 96 MiB or 10,000 unfinished obligations |
| Answer space of a started job | max_bytes × (7 + 6 × routes) and a little more, within 96 MiB; a run has at most one route, its message's conversation or the post channel |
| Gate | 64 events and 64 KiB of encoded events; timeout 120 s by default (up to 3,600 s), max_bytes 256 KiB by default (up to 1 MiB) |
| Wake | One pending per assistant; in from 1 s to 1 year, clamped to min (at least 60 s, default 600 s) and max (default 604,800 s); reason 280 characters |
| Completed bodies | 8 MiB budgets |
| Identity tombstones | 35 days |