Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/openhuman/agent_registry/agents/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,28 @@ mod tests {
"orchestrator must have read-only direct tool `{direct}`"
);
}
// Direct memory surface (#4762): recall/store are the product's
// core and must be first-class direct tools, not a sub-agent
// spawn — a trivial recall or a single "remember this" must not
// pay a blocking agentic round-trip (over-delegation, #4744) that
// can hang or return a 0-char result with persistence unconfirmed.
// Deep tree walks / reconciliation still delegate to
// `retrieve_memory` / `manage_profile_memory`.
for direct in ["memory_recall", "memory_store", "save_preference"] {
assert!(
tools.iter().any(|t| t == direct),
"orchestrator must have direct memory tool `{direct}` (#4762)"
);
}
// Memory-protocol close-out (#4116): a direct `memory_store` write
// obliges an `update_memory_md` index reconcile, so the tool that
// performs it must be in scope — otherwise the protocol's guidance
// is unsatisfiable and MEMORY.md (loaded here) drifts from the store.
assert!(
tools.iter().any(|t| t == "update_memory_md"),
"orchestrator must have `update_memory_md` to reconcile MEMORY.md \
after a direct memory_store (#4762)"
);
}
ToolScope::Wildcard => panic!("orchestrator must have named tool allowlist"),
}
Expand Down
30 changes: 30 additions & 0 deletions src/openhuman/agent_registry/agents/orchestrator/agent.toml
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,36 @@ named = [
"web_search_tool",
"web_fetch",
"http_request",
# Direct memory surface (#4762). Recall/store are the product's core and must
# be first-class DIRECT tools, not a sub-agent spawn: a trivial "what is my Q3
# OKR" recall or a "remember my Q3 OKR" write should not pay a blocking
# agentic round-trip (over-delegation, #4744) that can hang or — as observed —
# spawn `manage_profile_memory` which did 0 tool calls and returned a 0-char
# result, leaving the write's persistence unconfirmed. `memory_recall` reads
# the same store `memory_store` writes, so store→recall closes the loop inline
# with a real confirmation. Deep tree walks / reconciliation / people-graph /
# persona edits still delegate to `retrieve_memory` (agent_memory) and
# `manage_profile_memory` (profile_memory_agent) below. These are memory-store
# writes, NOT file/shell mutation — the "no write tools" rule (below) is about
# editing files and running commands, which stays out.
"memory_recall",
"memory_store",
Comment thread
M3gA-Mind marked this conversation as resolved.
"save_preference",
# Memory-protocol close-out (#4116). A successful `memory_store` is a durable
# write, so the memory-protocol middleware appends a "call `update_memory_md`
# to keep the MEMORY.md index in sync" note to the tool result and warns at run
# end if the index was never reconciled. Since the orchestrator now takes the
# direct-store path itself, it must own that closing step too — otherwise the
# guidance is unsatisfiable and MEMORY.md (which this agent loads,
# `omit_memory_md = false`) drifts from the store. `update_memory_md` is locked
# to the MEMORY.md / SKILL.md workspace index files (enum-gated, symlink-hardened),
# NOT a general file-editor: it is the index-sync counterpart of `memory_store`,
# so it belongs in the same memory bucket as the writes above — the "no write
# tools" rule (below) is about editing arbitrary files (`edit` / `file_write` /
# `apply_patch`) and running commands, which stay out. `save_preference` writes
# to the preference store and is deliberately NOT part of the MEMORY.md wiki, so
# it needs no reconcile.
"update_memory_md",
# Managed file-storage transfer surface for passing artifacts/attachments
# between chat, users, and workers. Storage lifecycle mutators
# (`storage_set_visibility`, `storage_delete_file`) stay out of the broad
Expand Down
3 changes: 2 additions & 1 deletion src/openhuman/agent_registry/agents/orchestrator/prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ Follow this sequence for every user message:
- **Do this even if remembered context could plausibly answer.** The user wants the live source of truth, not a stale summary.
- If the relevant toolkit is **not** in **Connected Integrations**, call `composio_connect { toolkit: "<slug>" }` **directly** to raise an **inline connect card** so the user can authorize in one click, then continue the task once it returns `connected: true`. Do **not** refuse based on the Connected Integrations list (that is only what is *already* connected, not what is *connectable*), do **not** make "go to Settings → Connections" your first move, and do **not** silently fall back to memory retrieval (see "Connecting external services" below).
3. **Can I solve this with direct tools?**
- Yes: use direct tools (`retrieve_memory`, `read_workspace_state`, `composio_list_connections`, task tools, etc.).
- Yes: use direct tools (`memory_recall`, `read_workspace_state`, `composio_list_connections`, task tools, etc.).
- **Memory is direct work.** Recalling a fact (`memory_recall`), storing a fact (`memory_store`), or saving a preference (`save_preference`) needs **no sub-agent** — call the direct tool and confirm the result. After a `memory_store` write, follow the memory protocol and call `update_memory_md` (targeting `MEMORY.md`) to keep the index in sync with the store; `save_preference` writes the preference store and needs no such reconcile. Reserve the `retrieve_memory` and `manage_profile_memory` **delegates** for genuinely deep work: multi-hop memory-tree walks, ingest/index into the long-term tree, reconciling overlapping notes, people-graph/alias management, or persona edits. Do **not** spawn a sub-agent for a single recall or a single "remember this".
- **Quick lookups are direct work.** Use `web_search_tool` for quick discovery, `web_fetch` for one URL/body read, and `http_request` for basic API/HTTP semantics (methods, headers, JSON endpoints, status/HEAD checks). Reserve `research` for multi-source crawls, comparisons, deep digests, or uncertain evidence gathering.
- **Read-only file lookups are direct work.** Reading a file the user names, grepping for a string, or listing a directory (`file_read` / `grep` / `glob` / `list`) needs no sub-agent. Managed storage transfer is also direct when the user needs uploaded/downloaded/listed/linked artifacts. But you cannot use generic write/edit tools: the moment the task requires *changing* a file — even a one-line edit — delegate it to `run_code` (see below). Never promise an edit you cannot make yourself.
- No: continue.
Expand Down
Loading