跪拜 Guibai
← All articles
Agent · Architecture · Artificial Intelligence

Lomo Agent: A Persistent Execution Architecture for Creative AI That Keeps Working While You Don't

By isboyjc ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

This post lays out a concrete reference architecture for agents that must run unattended for days, orchestrate paid external generation APIs, and recover from crashes without double-billing. Any developer building a long-horizon agent can borrow the routing, persistence, and concurrency patterns to avoid the failure modes that break chat-turned-agent products.

Summary

Lomo Agent, built on the Lomote AI creation platform, abandons the chatbot session model. Instead of asking users to create and manage conversations, it recognizes task boundaries, isolates execution context per goal, and routes messages to the right worker, whether a quick answer, a one-off image generation, or a long-running brand poster project. The system maintains a Main thread as router and spawns Task workers only when a goal needs sustained execution.

The architecture tackles the hard parts of long-running creative work: durable execution records model decisions and tool calls so crashes don't cause duplicate paid generations; an inbox decouples message arrival from model consumption so a new instruction can't race with an in-flight request; and a shared workspace with versioned objects and optimistic concurrency lets a user edit a storyboard while the agent generates a video from it. Memory is treated as source-tracked, versioned evidence with explicit revocation, so asking the agent to forget a color scheme actually propagates through derived summaries and profiles.

The article weighs trade-offs against other systems: Router/Worker separation borrows from DeepSeek's Super-agent, durable execution from Temporal, context engineering from Manus, and checkpoint/hook ideas from Claude Code. Key design choices include deterministic routing before semantic judgment, distinguishing message delivery from execution, classifying tasks as lightweight or persistent, and separating progress checks from creative acceptance. The author also describes fault-injection tests and end-to-end scenario drills that surface issues like the agent switching language mid-task and missing confirmation cards at human checkpoints.

Takeaways
— Lomo Agent uses a Main/Task structure: Main is the router, Task workers execute; only goals needing sustained advancement get a persistent execution space.
— Tasks are split into lightweight and persistent, with upgrades when a single generation evolves into a long-term creative project.
— Message routing uses deterministic rules first (task ID, object binding, card actions) and only falls back to a semantic Router when no explicit target exists.
— Model decisions and tool calls are persisted before execution, with idempotency keys (turn + step + call sequence) so crashes don't cause duplicate paid generations.
— Fencing tokens (execution generation counters) let a new Worker take over a task and reject stale writes from an old Worker.
— A persistent message inbox separates message delivery from consumption, so user edits arriving mid-generation wait for the next safe execution boundary.
— Long-term memory maintains source evidence, version chains, and derivation relationships, so forgetting a fact propagates through merged versions, episodic summaries, and user profiles.
— Human-in-the-loop checkpoints are stored as runtime state; the runtime auto-supplies a confirmation card if the model fails to ask.
— Shared workspace uses versioned objects and optimistic concurrency, rejecting stale writes while letting non-conflicting edits proceed.
Conclusions

The strongest claim is that a persistent runtime, not the model, should own task state and continuity; the model only plans and calls tools, while waiting, authorization, and recovery are deterministic system responsibilities.

Trading a transactional outbox for a database-as-source-of-truth plus a 10-second watchdog is a pragmatic cost/benefit balance: it accepts limited recovery latency in exchange for a much simpler scheduling mechanism.

The "forget" problem is more demanding than "remember": deleting an original user statement isn't enough because it propagates into merged versions, profile snapshots, and episodic summaries, forcing a source-tracking version chain.

Concepts & terms
Durable Execution
A pattern where the agent's execution state, model decisions, and tool call results are persisted so that after a crash or restart, the agent can resume without re-running the model or repeating side effects. References Temporal's design.
Fencing Token
A monotonic execution-generation counter incremented when a new worker takes over a task; each worker must present the current generation when writing state, so an old worker's late writes are rejected.
Optimistic Concurrency Control
Reading an object with a version and submitting changes with that version; the server rejects writes if the version has advanced, preventing overwriting concurrent edits.
Prompt Caching
Model API-level caching of the prompt prefix; the article notes stable system rules should be at the front to maximize cache hits, while dynamic task state goes in the tail.
Human-in-the-Loop Checkpoint
A persisted execution state where the agent pauses for user confirmation; the runtime ensures an actionable confirmation card is presented even if the model fails to ask.
From the discussion

Two fault lines emerge. One: long-term memory injects only date and content, never the source item, so model decisions can't trace back to original messages — the author admits this is a real risk and plans to surface source items in recall or re-weight by current context. Two: durable execution on the server (watchdog, database as source of truth) doesn't translate to mobile, where only the system can wake an app and offers no punctuality guarantee; a proposed remedy splits pure reminders from execution, reconciles idempotently on every wake, and returns the system's guarantee level so the model never claims false punctuality.

— Long-term memory strips source identifiers before injection; the source is stored separately for system use (cascade deletion, UI attribution) but the model can't see it, so project-specific conventions risk being treated as global preferences. Mitigations include marking source in recall results or adjusting weights by current item.
— Mobile persistence is incomplete: saved state doesn't survive the loss of scheduled alarms after reboot; BOOT_COMPLETED re-scheduling is needed, and missed alarms never fire.
— Doze and lack of exact alarm permission cause unpredictable delays with no system guarantee, so tool returns must include an exact flag to prevent the model from falsely claiming on-time reminders.
— The ledger answers what to do next but not when the wake-up will happen. Server-side solves this with a database and watchdog that re-derives wake-ups from state, at bounded latency, but mobile can't because only the system can wake and doesn't promise anything.
— A proposed mobile approach: separate pure reminders (pre-packaged, handed to system notifications) from execution tasks (server-run, phone only receives results); reconcile idempotently on every opportunity plus server push fallback; and schedule with the system's guarantee level, reporting actual vs planned time so runtime defines punctuality.
Featured comments
智测星球 1 likes

You write long-term memory as traceable profiles and facts. I haven't run Lomo. When I warm up the poster on Wednesday, does the recalled fact still carry its original item number?

isboyjc

Good question, the answer is no. The source (item and original message) is stored in the memory's source table, for the system to use: cascading undo on forgetting, displaying 'which memory, from which sentence' in the UI. Only the date and content are injected into the model. On Wednesday, 'a bit warmer' can find the original poster because the Router uses the item index to route the message back to the original item, which carries its own context; long-term memory only adds background like 'this person prefers low saturation.' I roughly understand what you mean — the problem you point out exists: the model can't see the source, so a project-specific convention might be taken as a global preference. Currently we only rely on the PROJECT category and time decay to mitigate this risk; later we're considering marking the source item in recall results, or adjusting weights by current item.

智测星球  → isboyjc

Thanks for the explanation.

booboosui

You wrote about persistent execution; I've hit the other half. The state is saved, but what wakes it up isn't persistent. No cron on mobile, only AlarmManager. When the system reboots, all scheduled alarms are lost. So you must listen for BOOT_COMPLETED and re-schedule every active todo. The one that's missed never rings. Then there's delay. I haven't applied for the exact alarm permission, so I can only fall back to setAndAllowWhileIdle, which can be minutes late under Doze. How late, the system doesn't say. So the tool return must include an exact=true/false flag. Without it, the model's next step will say 'reminded on time.' That lie comes from the permission, not the model. The ledger can answer 'what to do next,' but not 'when will I be woken up to do it.' I haven't gotten around this part.

isboyjc

That's a specific pitfall of the end side. Lomo Agent runs server-side, which is somewhat privileged: the database is the source of execution facts, the queue only handles waking, and if a message is lost a watchdog re-finds it every 10 seconds based on the database state. The watchdog itself re-registers idempotently at worker startup, so 'all alarms lost after reboot' becomes 'woken later' for us, not 'never rings.' Frankly, we've turned 'when will I be woken' into something derivable from the ledger, at the cost of bounded latency. That path doesn't work on mobile, because only the system can wake you, and the system offers no guarantee. On mobile, whether you get woken is decided by the system — I think of three directions for reference. First, separate reminders from execution: pure reminders prepare content at scheduling time and hand them to system alarms or local notifications; tasks that must execute at a specific time go to the server, and the phone just receives results. Second, don't expect a single wake to succeed; instead reconcile every time you wake: boot, update, timezone change, push, opening the app all go through the same idempotent reconcile; anything missed and overdue is immediately caught up, recording how late it was, and all future todos are re-registered; also add a server push fallback, deduplicating by todo id. Third, you can refine exactness: at scheduling time, return what level of guarantee the system gave, so the model says 'around 9 o'clock' from the start; after triggering, return planned time, actual time, and how late it was — the runtime determines punctuality, the model only relays it. That way the ledger still can't answer 'when will I be woken,' but it can answer 'what was missed and how late,' and at least neither the system nor the model has to lie.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗