everalgo-boundary
Chat boundary detection for EverAlgo — segments a flat list of ChatMessage objects into coherent MemCell slices using an LLM-based batch algorithm.
See the umbrella project: EverAlgo monorepo and the architecture document at docs/concepts/architecture.md.
Install
pip install everalgo-boundary
For the user-scenario class facade, install everalgo-user-memory instead — it re-exports BoundaryDetector which wraps this package.
What this distribution provides
| Symbol | Role |
|---|---|
detect_boundaries |
Low-level async function: (list[ChatMessage], *, llm, is_final, ...) → DetectionResult |
DetectionResult |
NamedTuple(cells: list[MemCell], tail: list[ChatMessage]) |
The class-style facades (BoundaryDetector for user-scenario chat, AgentBoundaryDetector for agent trajectories with tool calls) live in everalgo-user-memory and everalgo-agent-memory respectively.
Quick start
import asyncio
import json
from everalgo.boundary import detect_boundaries
from everalgo.llm.types import ChatMessage as LLMChatMessage, ChatResponse
from everalgo.testing.fake_llm import FakeLLMClient
from everalgo.types import ChatMessage
_BOUNDARY_JSON = json.dumps(
{"reasoning": "single topic", "boundaries": [], "should_wait": False}
)
async def main() -> None:
fake = FakeLLMClient(responses=[ChatResponse(content=_BOUNDARY_JSON, model="fake")])
messages = [
ChatMessage(id="m1", role="user", content="Let's talk about deployment.", timestamp=1_700_000_000_000, sender_id="u_alice"),
ChatMessage(id="m2", role="assistant", content="Sure — what's the target env?", timestamp=1_700_000_001_000, sender_id="assistant"),
ChatMessage(id="m3", role="user", content="K8s. Switching topic: lunch?", timestamp=1_700_000_002_000, sender_id="u_alice"),
]
# Streaming: hold `tail` between calls; pass prior tail + new messages each time.
result = await detect_boundaries(messages, llm=fake)
cells, tail, should_wait = result # NamedTuple unpacking
# `should_wait` is the LLM's verdict on the tail, not a restatement of it being non-empty: True
# means the trailing segment carries too little to place in an episode yet (media placeholders
# only, a bare "ok", a system notification, an ambiguous 30-min-to-4-hour gap). A caller that
# extracts on every non-empty tail extracts from those; one that waits on every non-empty tail
# never extracts at all. `None` means no path judged it — see the DetectionResult docstring.
# End-of-session: tail is forced into the last cell.
result = await detect_boundaries(messages, llm=fake, is_final=True)
assert result.tail == []
for mc in result.cells:
print(mc.timestamp, len(mc.items))
asyncio.run(main())
The streaming state machine
detect_boundaries deliberately holds back trailing messages as tail — the LLM cannot know whether a conversation continues beyond the last seen message. The caller maintains state:
tail: list[ChatMessage] = []
for batch in incoming_batches:
result = await detect_boundaries(tail + batch, llm=client)
await persist(result.cells)
tail = result.tail
# Session ends — flush everything.
final = await detect_boundaries(tail, llm=client, is_final=True)
await persist(final.cells)
Tokenizer utilities
everalgo._tokenize (in everalgo-core) exposes two module-private utilities used by boundary algorithms; not part of the public surface:
count_tokens(text: str) → int— token count under OpenAIo200k_baseencoding viatiktoken.force_split(text: str, *, max_tokens: int) → list[str]— last-resort token-bounded chunking; no semantic awareness.
Stubs
WorkspaceMemCellExtractor (Jira / Email / Confluence) is a placeholder in v0.x — all methods raise NotImplementedError. It is deliberately excluded from everalgo.boundary.__all__; import it from everalgo.boundary.workspace directly if you need the reserved name. Implementation lands in a future minor bump when the RawData contract is finalised.
Related distributions
everalgo-user-memory—BoundaryDetectorclass facade for chat scenarioseveralgo-agent-memory—AgentBoundaryDetectorclass facade for agent trajectories
Metadata
Release files for everalgo-boundary 0.3.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| everalgo_boundary-0.3.0.tar.gz | 23.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| everalgo_boundary-0.3.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 41.9 kB
Release files / everalgo_boundary-0.3.0.tar.gz
| Download URL | everalgo_boundary-0.3.0.tar.gz |
|---|---|
| Size | 23.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
761c0ffdf4234bc641436db79d9211f809154580fb65178af3c9e64dd6bbd443
|
|
BLAKE2b-256 checksum How to use checksums |
57ba8cd039fdc848d45ade53a5db47a01a5db34b4664d0505b23c4adefc97d92
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|
Release files / everalgo_boundary-0.3.0-py3-none-any.whl
| Download URL | everalgo_boundary-0.3.0-py3-none-any.whl |
|---|---|
| Size | 18.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a6a037bb3ecf36ce07db4ad168757cbc6e745f5d1acf427ff10e0d827402b5e5
|
|
BLAKE2b-256 checksum How to use checksums |
2427fc7fc40581a0be93039764ef6e38de56fadd937bf93022ae10c179534c75
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.12.12
|