Releases: BackendStack21/odek
v1.7.0
Highlights
odek v1.7.0 is a security-and-resilience release: it hardens the agent against several real-world failure modes (infinite hangs, prompt-injection-driven escalation, SSRF, a serve-mode deadlock) and adds conversational continuity for scheduled tasks. Everything here is backwards-compatible — no config changes required.
🔒 Security hardening
- No more sandbox escape via
~/.odek/. A confined/untrusted sub-agent could previously rewrite its ownconfig.json(disable the sandbox, enable YOLO mode), drop an auto-loadedSKILL.md, or overwrite shell rc files. Those trust anchors are now protected and the write tools are confined. (#30) - SSRF & DNS-rebinding blocked. Web/HTTP tools now re-check the resolved IP at dial time and refuse internal targets (cloud metadata
169.254.169.254,10.x,192.168.x, IPv6 ULA), closing the gap where a hostname that looks external resolves to an internal address. (#31)
🛡️ Reliability & recoverability
- The browser approval prompt works again. A serve-mode deadlock made every Web UI approval time out and get denied; fixed, along with a data race that could crash
serveunder parallel tool calls. (#32) - Tools can no longer hang the agent forever.
shell(and the other long-running tools) now honor a timeout and Ctrl-C / turn cancellation — a stuck command is killed instead of wedging the session. (#34) - Sturdier LLM calls & durable state. Secondary LLM calls now retry, rate limits honor
Retry-After, and session/memory writesfsyncbefore rename so a crash can't lose your latest turn. (#34) - Crash-safe batch tools. Centralized the batch-tool parallelism behind one panic-recovering helper — a single bad input can no longer take down the whole agent. (#33)
✨ New
- Scheduled tasks now feed back into the conversation. When a scheduled job posts its result to a Telegram chat, that exchange is recorded into the chat's session — so you can follow up ("what did that scheduled task find?") and the agent remembers. The run itself stays isolated and deterministic. (#35)
🩹 Fixes & docs
- Fixed
/neworphaning the per-chat mutex and raised the sub-agent stdout scan cap. (#29) - Brought the landing-page IDENTITY.md example in line with the shipped system prompt (incl. the prompt-injection detection section). (#36)
What's Changed
- fix(concurrency): stop /new orphaning per-chat mutex; raise sub-agent stdout scan cap by @jkyberneees in #29
- fix(security): close ~/.odek/ write carve-out privilege escalation by @jkyberneees in #30
- fix(security): add dial-time IP guard to stop SSRF / DNS-rebinding by @jkyberneees in #31
- fix(serve): break approval deadlock + race in wsApprover by @jkyberneees in #32
- perf(tools): centralize batch parallelism with panic-safe helper by @jkyberneees in #33
- fix: tool resilience & crash-durable persistence (5 fixes) by @jkyberneees in #34
- feat(schedule): record delivered Telegram results into the chat session by @jkyberneees in #35
- docs(site): bring the IDENTITY.md example up to date with the system prompt by @jkyberneees in #36
Full Changelog: v1.6.0...v1.7.0
v1.6.0
What's Changed
- Centralized embedding backend: semantic memory, session_search & skill matching by @jkyberneees in #28
Summary
Centralized Embedding Backend
All embedding functionality is now consolidated into a new internal/embedding/ package, shared across semantic memory, session search, and skill matching. Previously each subsystem managed its own embedding logic independently.
Changes by Area
New internal/embedding/ package
- Unified embedding client with HTTP backend support
- Featurization helpers moved from
internal/memory/ - Comprehensive edge-case tests
Skill Matching (internal/skills/)
vector_matcher.goextended to use the centralized embedding backend- New HTTP integration tests (
vector_matcher_http_test.go)
Session Search (internal/session/)
vector_index.gorefactored to delegate to the shared embedding backend- New HTTP integration tests (
vector_index_http_test.go)
Memory (internal/memory/)
embedder.gosignificantly slimmed down — now a thin wrapper over the centralized backend- Mock added for unit testing without a live embedding server
Config (internal/config/)
- New
loader.gowith tests for embedding backend configuration
Docker
docker-compose.yml,Dockerfile.embeddings,.env.example, and config files updated to reflect the new backend setup
Docs
- New
docs/LEARNING.md docs/CONFIG.mdexpanded with embedding backend configuration referencedocs/MEMORY.md,docs/SESSIONS.md, and Docker guide updated
Full Changelog: v1.5.0...v1.6.0
v1.5.0
What's Changed
- fix(loop): deliver recovered tool-panic message to the LLM + review cleanups by @jkyberneees in #26
- feat(memory): pluggable semantic embeddings via go-vector v1.3.0 by @jkyberneees in #27
Full Changelog: v1.4.0...v1.5.0
v1.4.0
What's Changed
- feat(web_search): SearXNG-backed web_search tool + Docker sidecar by @jkyberneees in #24
- fix(security): audit remediation — Telegram path traversal + approval-grant leak by @jkyberneees in #25
Full Changelog: v1.3.0...v1.4.0
v1.3.0
Highlights
odek can now see. This release adds local image and video understanding through a new vision tool powered by MiniCPM-V 4.6 — a compact 1.3B multimodal model that runs entirely on your own machine via llama-mtmd-cli. No cloud API, no keys, no per-image cost. The model and runtime are baked straight into the container image, so it works out of the box: hand the agent an image and it describes what's there (including any visible text); hand it a video and odek samples frames and reasons over them together.
The Telegram bot gets the biggest day-to-day upgrade from this. Send it a photo and it now describes the image first, then answers — and if you add a caption like "what does this error say?" or "is this safe to eat?", that caption becomes your question and focuses what the model looks at. Two papercuts are gone too: photos no longer collide onto the same filename (so the bot stops saying "already processed" when you send a second image), and image text is wrapped as untrusted content so a screenshot can't smuggle instructions into the agent.
Under the hood, the container build was hardened so the vision binary links cleanly against the runtime image (built from source to avoid a glibc mismatch), keeping the zero-setup promise intact across amd64 and arm64.
What's Changed
- feat(docs): hero "zero → telegram" carousel + doc-link refresh by @jkyberneees in #20
- feat(vision): add vision tool using MiniCPM-V 4.6 (1.3B) via llama-mtmd-cli by @jkyberneees in #22
- feat(telegram): unique photo filenames + caption-aware auto-vision by @jkyberneees in #23
Full Changelog: v1.2.0...v1.3.0
v1.2.0
Highlights
This release matures odek's memory subsystem into a full episode lifecycle, replaces the external cron dependency with a native in-process scheduler, and moves the container image to a Debian bookworm-slim base. Together these make long-running agents remember more reliably, schedule work without extra binaries, and ship on a broader, glibc-based runtime.
- Memory — episode lifecycle: dedup-on-write plus eviction by cap/TTL, a persisted go-vector episode index with better featurization, deterministic (no-LLM) buffer turn-summaries, and auto-extraction of durable facts at session end (trusted sources only).
- Memory — safety & provenance: path-aware episode/skill provenance with human-gated promotion, and observability signals across the memory and agent-loop lifecycle.
- Memory — performance: AddFact no longer makes a synchronous LLM call; consolidation runs in the background at session end.
- Native scheduler: an in-process task scheduler retires the external supercronic dependency, with scheduled reminders built in.
- Docker: the runtime image migrates to
debian:bookworm-slim, and whisper.cpp + the tiny model are bundled for out-of-the-box transcription. - Config & housekeeping: dropped
github_repo_directory/github_repo_url, added memory config sections to the compose files, and fixed order-dependent loader tests.
What's Changed
- feat(docker): scheduled reminders via supercronic by @jkyberneees in #6
- feat(schedule): native in-process task scheduler (retires supercronic) by @jkyberneees in #7
- refactor(config): remove github_repo_directory and github_repo_url by @jkyberneees in #8
- feat(docker): bundle whisper.cpp + tiny model for out-of-the-box transcription by @jkyberneees in #9
- feat(memory): path-aware episode/skill provenance + human-gated promote by @jkyberneees in #10
- feat(memory): auto-extract durable facts at session end (trusted-only) by @jkyberneees in #11
- feat(memory): persisted go-vector episode index + featurization quality by @jkyberneees in #12
- perf(memory): remove sync LLM from AddFact; background consolidation at session end by @jkyberneees in #13
- chore(docker): add memory config sections to compose configs by @jkyberneees in #14
- fix(config): isolate global state in loader tests to fix order-dependent failures by @jkyberneees in #15
- feat(memory): deterministic buffer turn-summaries (no LLM) by @jkyberneees in #16
- feat(memory): episode lifecycle — dedup-on-write + eviction (cap/TTL) by @jkyberneees in #17
- Add observability for memory + agent-loop lifecycle signals by @jkyberneees in #18
- build(docker): migrate image to Debian bookworm-slim by @jkyberneees in #19
Full Changelog: v1.1.0...v1.2.0
v1.1.0
What's Changed
- fix(redact): close secret-leak gaps on the tool output surface by @jkyberneees in #4
- harden(danger): close classifier evasion vectors + fail closed on unknown commands by @jkyberneees in #5
Full Changelog: v1.0.4...v1.1.0
v1.0.4
What's Changed
- fix(approval): always render the full command in approval prompts by @jkyberneees in #3
Full Changelog: v1.0.3...v1.0.4
v1.0.3 — Sub-agent system prompt is a fixed trust boundary
v1.0.3 — Sub-agent system prompt is a fixed trust boundary
🔒 Security
- subagent: the sub-agent system prompt is now a fixed, code-defined constant that the parent agent cannot write to. Previously
delegate_tasksexposed asystemfield that replaced the prompt wholesale (dropping the SAFETY/anti-injection block), andbuildSubagentPromptembedded the raw, parent-supplied goal text directly into the system message. Since a parent'sgoal/contextcan carry text it ingested from untrusted sources (fetched pages, MCP output, files), a prompt-injection payload could redefine a sub-agent's identity or strip its safety rules. That vector is now closed.
What changed
- All parent steering (
goal+guidance+context) is delivered in the sub-agent's request, never spliced into the system prompt (buildSubagentRequest). - The
delegate_taskssystemfield is removed and replaced byguidance— "how to approach the task," request-level.ODEK_SYSTEM/ configsystemno longer apply to sub-agents. - The fixed prompt's SAFETY block is hardened (request content is data, not identity; never read secrets).
- When
trust_level: "untrusted", the request body is wrapped in an<untrusted_input>fence — defense-in-depth alongside the existingapplySubagentTrustpermission clamp.
Tests & docs
- New
subagent_prompt_isolation_test.go: the system prompt is unaffected by hostile parent input; the request carries goal/guidance/context; untrusted tasks are fenced. - Updated tool-schema and e2e tests (
system→guidance); rewrotedocs/SUBAGENTS.mdanddocs/SECURITY.md§7.
⚠️ Behavior change
The system field on delegate_tasks is gone (use guidance), and ODEK_SYSTEM/config system no longer affect sub-agents. The tool schema is regenerated each run, so there are no external consumers; the dynamic persona auto-selection is intentionally dropped in favor of explicit guidance.
Full Changelog: v1.0.2...v1.0.3
v1.0.2 — Telegram system prompt fix
v1.0.2 — Telegram system prompt fix
🐞 Bug Fixes
- telegram: seed the system prompt into the chat history so
IDENTITY.md(and the default prompt) actually reach the model. Telegram ran the agent viaRunWithMessageswithout seedingmessages[0], so chats reached the LLM with no system prompt and the agent answered as the provider's base identity (e.g. "I am Claude"). Now seeded for new chats and refreshed for resumed ones, soIDENTITY.mdedits take effect on the next turn. Covers text, voice, photo, and command messages; regression test added. - docker: drop
network_mode: nonefrom the Godmode example — it blocked the outbound LLM API call, so the agent couldn't run at all.
✨ Features
- docker: install the GitHub CLI (
gh) in the image; documentGH_TOKENandGIT_AUTHOR_*/GIT_COMMITTER_*env vars for git/gh setup.
📚 Docs & Docker
- Add a runnable
docker/Docker Compose setup with four profiles — Restricted, Godmode, and their Telegram variants — plus a fullDOCKER_COMPOSE_USER_GUIDE.md. - Store Telegram state (sessions, skills, lock) in an external
./.odekfolder instead of a named volume. - Document in the Dockerfile how to add extra runtimes (Node.js, Python, Bun) or switch to a Debian base.
- Align the Anthropic model example with the documented
claude-sonnet-4profile.
Full Changelog: v1.0.1...v1.0.2