OpenMuse 0.5.0
The agent sees what you send it and finds what it knows. Photos and files go from the phone into a message and the agent works from what is in them — a picture to a model that takes images, a PDF read as text; memories come back by what they mean, not only by the words they share with the message; and web search has a provider with an API behind it when DuckDuckGo's scraping is not enough.
Added
- Attachments in chat. The paperclip (or a paste) attaches photos and files to a message — a receipt, a contract PDF, a spreadsheet, ten at most, 25 MB each (
server.max_upload_mb) — from the camera, the photo library or the phone's files. They upload as you pick them (POST /api/files/upload), show as thumbnails and chips, and a message may be attachments alone. Each lands in the workspace underattachments/<date>/, so it is in the Library and every tool can use it, and the message lists them for the agent with what they are. Pictures go to the model as images when it takes them (llm.vision = auto, the default): scaled to 1568 px first so a phone photo costs what a small one does; when the endpoint refuses image content — DeepSeek, an Ollama model without vision — the same request goes out with the text only, pictures are dropped for the rest of the run, the user is told once, and the model is told which pictures it cannot see so it does not describe what it never saw (oninsists,offnever sends them). PDFs are read as text byfiles, page by page — a scanned one says it has no text layer.POST /api/threads/{id}/sendtakesfiles; the user bubble shows the pictures and file chips, tap to open. - Recall by meaning. Keyword recall finds a memory when the message shares a word with it; it misses "写邮件给房东" → "the landlord is Bob Li" and "book a flight" → "prefers a window seat". With an embedding endpoint those are found: every memory is embedded once (the vector is kept in
memory.dbnext to a hash of the text, so a changed line is embedded again and a switch back to a model is free), the message is embedded per turn, and the memories whose closeness stands out are fused with the keyword ranking by reciprocal rank — the two agree often, and where they do not, both get a say. Any OpenAI-compatible/embeddingsworks: OpenAI, Ollama withqwen3-embedding:0.6bpulled (the default there — small, reads Chinese and English), OpenRouter, a gateway. DeepSeek has none, so with it pointmemory.embedding_base_urlat one that has — Ollama next to DeepSeek — or recall stays by keyword.memory.embeddings = auto(the default) tries the endpoint once per start and falls back quietly, one failed call rather than one per turn;oninsists anddoctorfails when it cannot;offnever embeds. A key of its own goes to the vault asEMBEDDINGS_API_KEY; the gateway headers of the chat endpoint never go to another one. Connections → Recall by meaning sets and tests it (the test indexes every memory on the spot and the card says how many);openmuse memory recall "…"shows the fused ranking with each memory's closeness;openmuse doctorreports the model, the dimensions and the count;PUT /api/connections/embeddings,POST /api/connections/embeddings/test. Therecalltool and the memories in the system prompt both use it; a recall that fails for any reason falls back to the keyword ranking and never stops a turn. - Web search providers.
web_searchis answered by DuckDuckGo out of the box, as before, or by Brave Search or Tavily with a key, or by a SearXNG instance you run —[connectors.search], or Connections → Web search on the phone, where the key goes to the vault asSEARCH_API_KEYand Test runs one search. Whichever is picked, a search that fails (a lapsed key, a rate limit, an instance that is down) is answered by DuckDuckGo instead, once, with a note on top of the results, so a task goes on. The tool'sregiongoes to every provider in its own terms. The provider's host is a destination you chose, so taint tracking treats it like the allowlist (CallAssessment.egress_configured).openmuse doctorreports the provider and whether it has what it needs;OPENMUSE_SEARCH_PROVIDER/_API_KEY/_BASE_URLfor Docker.
pip install -U openmuse · uv tool upgrade openmuse · docker pull ghcr.io/openmuseagent/openmuse:0.5.0. Full list of changes: CHANGELOG.md.