<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Manuel Bruña</title>
    <description>The latest articles on DEV Community by Manuel Bruña (@tecnomanu).</description>
    <link>https://dev.to/tecnomanu</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F938087%2Fadc3c6af-233f-4eb1-90c8-37af70ebe3f2.jpeg</url>
      <title>DEV Community: Manuel Bruña</title>
      <link>https://dev.to/tecnomanu</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/tecnomanu"/>
    <language>en</language>
    <item>
      <title>Why I Made APX Forward a Message as a Quote, Not a Paste</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Mon, 05 Oct 2026 13:04:48 +0000</pubDate>
      <link>https://dev.to/tecnomanu/why-i-made-apx-forward-a-message-as-a-quote-not-a-paste-1kl</link>
      <guid>https://dev.to/tecnomanu/why-i-made-apx-forward-a-message-as-a-quote-not-a-paste-1kl</guid>
      <description>&lt;p&gt;I kept hitting the same small failure while building APX: a useful message existed, but it lived in the wrong conversation.&lt;/p&gt;

&lt;p&gt;A person would receive a detail in one thread, open another agent session, copy the text, and paste it there. The new agent could read the words, but not their meaning in context. Was this something the owner had just typed? Was it an agent's conclusion? Which project or conversation produced it? Could anyone reopen the original exchange next week?&lt;/p&gt;

&lt;p&gt;Copy-paste is fast, but it quietly destroys the facts that make a handoff trustworthy.&lt;/p&gt;

&lt;p&gt;So I made forwarding in APX a quote with provenance, not a convenience paste.&lt;/p&gt;

&lt;h2&gt;
  
  
  The thesis: context needs an address
&lt;/h2&gt;

&lt;p&gt;A forwarded message now carries where it came from, who said it, and when it was said. In the web surface, a message can move to another session in the same project or a different project. The destination receives a quote card rather than an anonymous paragraph.&lt;/p&gt;

&lt;p&gt;That is deliberately modest. I did not add a new message channel, a separate forwarding database, or an opaque cross-project synchronization layer. A forwarded item is still an ordinary user turn. It is stored in the same places other turns are stored, so existing conversation views, ledgers, inboxes, and later re-reads do not need a special alternate history.&lt;/p&gt;

&lt;p&gt;The turn's metadata holds the structured provenance. The text delivered to the model holds an explicit quote marker containing the source label, speaker, and timestamp. The model and the human therefore get the same important distinction: these are quoted words, not a fresh instruction from the owner.&lt;/p&gt;

&lt;p&gt;That dual representation matters. Metadata lets the UI render a readable quote card and navigate back toward its source. The explicit marker lets an agent reason about the quote without guessing where it came from. If I kept only metadata, the model would lose the boundary. If I kept only a magic text prefix, every client would need to parse presentation details from prose.&lt;/p&gt;

&lt;h2&gt;
  
  
  The small details were the feature
&lt;/h2&gt;

&lt;p&gt;Most of the work was not the forward button. It was deciding what a forward may carry and what it must not pretend to be.&lt;/p&gt;

&lt;p&gt;First, the quote is bounded. APX caps forwarded text at 4,000 characters and marks it as truncated when needed. A forward is context, not a back door for injecting a giant transcript or binary-looking tool output into another model's context window. The destination still has room to answer.&lt;/p&gt;

&lt;p&gt;Second, the source has a real address. Depending on where the message began, APX records enough information to identify a thread, conversation, or live session. It also records the originating project. That last part is essential when a forward crosses projects: an ID only makes sense inside its own project. Without project identity, a card may point at the wrong conversation or nowhere at all.&lt;/p&gt;

&lt;p&gt;Third, author identity stays intentionally simple. The forwarded payload distinguishes the owner from an agent and may include an agent display name. That is enough to prevent the worst ambiguity without inventing a complicated hierarchy of new message types.&lt;/p&gt;

&lt;p&gt;Finally, I put the quote before the note the person adds at forwarding time. A message such as “review this and extract risks” is useful only if the agent can first see what “this” is. The quote also uses blockquote lines and a closing marker, so multi-paragraph content does not blur into a new instruction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why an ordinary turn was better than a transport feature
&lt;/h2&gt;

&lt;p&gt;I was tempted to treat forwarding as a transport concern: copy a payload from one chat object to another and call it done. That would have created a strange exception. It might work in one panel, yet disappear from a ledger, fail to survive a refresh, or become unreadable on another APX surface.&lt;/p&gt;

&lt;p&gt;Making it an ordinary user turn with extra provenance has a calmer result. The destination session owns the new turn. The source remains unchanged. The destination can reply naturally. Existing storage and message shaping keep doing their jobs.&lt;/p&gt;

&lt;p&gt;This also avoids an important false promise: forwarding is not shared memory. It does not merge two sessions, make their histories identical, or grant one project access to another project's entire conversation. It carries one bounded quotation, visibly labeled, because a person chose to hand it over.&lt;/p&gt;

&lt;p&gt;That boundary is useful for daily work. I can send an agent's investigation from one session to a reviewer in another and ask a focused question. I can move a customer detail from a channel conversation to a project session without presenting it as something I personally wrote. I can revisit the destination later and see both the quote and the instruction that accompanied it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned
&lt;/h2&gt;

&lt;p&gt;Agent products often make moving text look trivial. But when an agent acts on text, provenance is part of the input. Losing it changes the meaning of the handoff.&lt;/p&gt;

&lt;p&gt;The practical rule I am keeping is simple: when context crosses a conversation boundary, preserve the boundary in the artifact. Keep the quote bounded. Name its source. Name its speaker. Keep the original available to reopen. Do not turn a handoff into a silent copy.&lt;/p&gt;

&lt;p&gt;That is a smaller feature than “cross-agent collaboration” sounds like. It is also more honest. APX does not need every conversation to become one giant memory. It needs a reliable way for a human to carry one useful piece of context into the next room.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
    </item>
    <item>
      <title>A Project Needs Two Memories—But Only One Should Travel With Git</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Mon, 05 Oct 2026 12:03:57 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/a-project-needs-two-memories-but-only-one-should-travel-with-git-40e1</link>
      <guid>https://dev.to/agentprojectcontext/a-project-needs-two-memories-but-only-one-should-travel-with-git-40e1</guid>
      <description>&lt;h1&gt;
  
  
  A Project Needs Two Memories—But Only One Should Travel With Git
&lt;/h1&gt;

&lt;p&gt;Agent projects collect facts quickly: a deployment detail mentioned in a chat, a local preference discovered during a run, a decision that belongs in the repository. Treating all of them as one memory creates a bad choice: either private runtime details leak into Git, or durable project knowledge remains trapped on one machine.&lt;/p&gt;

&lt;p&gt;APX and APC avoid that choice by giving a project two memories with different jobs. The practical rule is simple: let APX retain newly captured project notes locally; promote only reviewed, team-safe facts into APC.&lt;/p&gt;

&lt;h2&gt;
  
  
  The memory that stays local
&lt;/h2&gt;

&lt;p&gt;APX keeps local project memory under its own runtime state, outside the repository. This is the right destination for facts gathered while operating: a note from a conversation, a temporary constraint found during a task, or a detail that may include information not meant for every future clone.&lt;/p&gt;

&lt;p&gt;That separation is deliberate. A note captured automatically can contain material supplied through a chat or session. Committing it immediately makes it durable, shared, and hard to retract. Local runtime memory lets APX use the fact during daily work without silently turning it into project policy.&lt;/p&gt;

&lt;p&gt;For example, an agent may record that a current task depends on a local service configuration. That can help the next APX turn on the same machine. It does not automatically mean every contributor should inherit it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The memory that travels
&lt;/h2&gt;

&lt;p&gt;APC's &lt;code&gt;.apc/memory.md&lt;/code&gt; has a stricter role: curated project facts safe for the team. It lives in the repository, so Git carries it through clones, reviews, and history. That makes it useful for decisions that should outlast a runtime session: an architectural boundary, a durable convention, or a confirmed operational constraint.&lt;/p&gt;

&lt;p&gt;The important boundary is authorship. APX does not treat a newly captured runtime note as permission to write the curated APC file. A person reviews the fact and decides whether it belongs in the shared project contract. The Memories surface can show both halves, but their visibility does not erase their different trust levels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why two memories improve daily work
&lt;/h2&gt;

&lt;p&gt;A single memory store forces every note to be either too private to share or too easy to commit. The two-part design gives each fact a safe first home:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Capture working context locally in APX.&lt;/li&gt;
&lt;li&gt;Keep using it while the local runtime needs it.&lt;/li&gt;
&lt;li&gt;Review whether it is durable and safe for the team.&lt;/li&gt;
&lt;li&gt;Promote only that smaller set into &lt;code&gt;.apc/memory.md&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This also keeps APC portable. A fresh clone receives the decisions needed to understand the project, not another operator's conversations or machine-specific residue. Meanwhile, APX remains useful as the local runtime that can retain short-lived operational context.&lt;/p&gt;

&lt;p&gt;The thesis is not that local notes are lesser knowledge. They are knowledge with a different audience and lifetime. APC makes shared context explicit; APX makes daily context usable without confusing it for a Git artifact. Keep both, but promote deliberately.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Local Agent Panel Should Not Need a Cloud Project Mirror</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Sat, 03 Oct 2026 12:03:44 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/a-local-agent-panel-should-not-need-a-cloud-project-mirror-2k5c</link>
      <guid>https://dev.to/agentprojectcontext/a-local-agent-panel-should-not-need-a-cloud-project-mirror-2k5c</guid>
      <description>&lt;h1&gt;
  
  
  A Local Agent Panel Should Not Need a Cloud Project Mirror
&lt;/h1&gt;

&lt;p&gt;A browser panel can make an agent system feel like a hosted product. That does not mean the project must be copied to a hosted product. APX takes a different boundary: the panel is a local interface to a local daemon, while APC keeps durable project context in the repository.&lt;/p&gt;

&lt;p&gt;That distinction is practical. A project needs rules, agent definitions, reusable skills, and curated memory that can travel with its Git history. A running system needs sessions, conversation threads, logs, a scheduler, and active connections that should stay on the machine operating them. Treating both as one cloud-shaped data store weakens both jobs.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. Its project contract lives in &lt;code&gt;AGENTS.md&lt;/code&gt; and &lt;code&gt;.apc/&lt;/code&gt;: files a teammate can review, version, and clone. APX is the daily-use runtime layer. It reads that context, runs agents, and keeps runtime state under &lt;code&gt;~/.apx/&lt;/code&gt; instead of turning the repository into a session database.&lt;/p&gt;

&lt;h2&gt;
  
  
  The panel is a surface, not another source of truth
&lt;/h2&gt;

&lt;p&gt;APX's web admin is served by the local daemon. By default, that daemon listens on &lt;code&gt;127.0.0.1:7430&lt;/code&gt;; the CLI, web panel, desktop window, TUI, and MCP bridge communicate with the same local process over HTTP. One runtime can therefore expose several interfaces without making each interface own a separate copy of projects, agents, or conversations.&lt;/p&gt;

&lt;p&gt;Start with a normal status check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;apx status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If needed, APX starts its daemon. Opening &lt;code&gt;http://127.0.0.1:7430&lt;/code&gt; then shows the panel backed by that same daemon. The browser is useful because it is a good surface for browsing projects, sessions, messages, MCPs, and routines—not because it becomes a new project backend.&lt;/p&gt;

&lt;p&gt;This design avoids a common drift problem. Imagine editing an agent role in a dashboard while the repository still has an older agent definition. Now a reviewer must ask which source an agent will actually follow. APC avoids that ambiguity by keeping durable project meaning in ordinary files. APX can index and use those files, but its live state remains runtime-owned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local by default, explicit when shared
&lt;/h2&gt;

&lt;p&gt;A local panel is not automatically a network service. APX binds the daemon to loopback by default. To open the panel from another device on a LAN, the operator must opt in and pair that client. That is a meaningful boundary: browser access can expand deliberately without silently exposing the daemon on every network.&lt;/p&gt;

&lt;p&gt;The same separation helps with recovery. Removing a project from APX's registered-project list does not delete project files. Cloning the repository elsewhere still brings the APC contract; it does not bring someone else's local conversations, tokens, or daemon process.&lt;/p&gt;

&lt;p&gt;There is no claim that local runtime state eliminates every external dependency. An agent may call a configured model provider or an MCP server. The point is narrower: APX does not require a public server merely to give a local project a usable agent dashboard.&lt;/p&gt;

&lt;p&gt;Use the boundary as a design test. If a fact should survive a clone and code review, put it in APC. If it only exists because an agent is running right now, let APX keep it local. The panel can be rich without becoming a cloud mirror of your project.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Read Your Own AGENTS.md Whole; Bound Foreign Context</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:03:01 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/read-your-own-agentsmd-whole-bound-foreign-context-1lmh</link>
      <guid>https://dev.to/agentprojectcontext/read-your-own-agentsmd-whole-bound-foreign-context-1lmh</guid>
      <description>&lt;h1&gt;
  
  
  Read Your Own AGENTS.md Whole; Bound Foreign Context
&lt;/h1&gt;

&lt;p&gt;An agent runtime has two conflicting duties when it loads project instructions: preserve the rules that govern its own work, and keep an arbitrary external file from consuming the entire prompt. Treating both files the same creates a bad trade-off. A small universal limit can silently remove a project’s own critical rules; no limit lets any referenced repository take over the context window.&lt;/p&gt;

&lt;p&gt;APX makes the distinction explicit. It treats APC as the portable context layer: &lt;code&gt;AGENTS.md&lt;/code&gt; and the defined &lt;code&gt;.apc/&lt;/code&gt; files carry project-owned guidance. APX is the daily-use runtime and tooling layer that assembles this guidance into a live prompt, along with runtime state that remains local.&lt;/p&gt;

&lt;p&gt;The practical rule is simple: APX reads the &lt;code&gt;AGENTS.md&lt;/code&gt; for the project it is running inside in full. A foreign project’s file has a configurable budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why one cap fails
&lt;/h2&gt;

&lt;p&gt;Imagine a project’s &lt;code&gt;AGENTS.md&lt;/code&gt; starts with code conventions and ends with a release safety rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gu"&gt;## Release&lt;/span&gt;

Never publish before the integration suite passes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A fixed cap can preserve the first section and cut the last one. The agent then receives a partial contract while believing it received project guidance. That is worse than a visible absence: it can follow some rules and violate rules it never saw.&lt;/p&gt;

&lt;p&gt;APX had exactly this failure mode. Its prompt-builder regression test records that an earlier 6,000-character cap sliced the owning project’s contract mid-rule. The current implementation does not cap the project matching the runtime’s working directory. The project’s own contract reaches the prompt whole.&lt;/p&gt;

&lt;p&gt;That is not a claim that every instruction file should be unlimited everywhere. It is an ownership decision. The repository running the agent owns its contract and should be able to review its full effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Foreign context needs a different policy
&lt;/h2&gt;

&lt;p&gt;APX can also receive a project path that is not its own working project. That file might be useful context, but it is not safe to assume its size is reasonable for the current turn. APX therefore applies a default foreign-contract budget of 24,000 characters.&lt;/p&gt;

&lt;p&gt;When it must shorten a file, it does two important things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It cuts on a line boundary instead of breaking a rule mid-sentence.&lt;/li&gt;
&lt;li&gt;It states that the result is truncated and reports how much was omitted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The resulting prompt tells the agent to read the file directly before relying on rules not shown. This preserves an important fact: partial context is partial.&lt;/p&gt;

&lt;p&gt;The foreign cap is also configurable through &lt;code&gt;super_agent.project_agents_max_chars&lt;/code&gt;. A positive value changes the budget; &lt;code&gt;0&lt;/code&gt; disables it. That makes prompt size a deliberate local runtime choice, not a hidden change to APC’s portable contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the boundary clear
&lt;/h2&gt;

&lt;p&gt;This division helps answer a common design question: should a project shorten its own instructions to fit a runtime? Sometimes, yes—but that should be a project authoring decision, made in the repository and reviewed like any other change. It should not be an invisible runtime truncation.&lt;/p&gt;

&lt;p&gt;Likewise, a runtime may need to bound external context for cost and reliability. That safeguard belongs in APX, where prompt assembly happens. It does not redefine what APC files mean or what a project is allowed to document.&lt;/p&gt;

&lt;p&gt;A useful test follows: when an agent acts inside your repository, can you show exactly which project rules reached it? If the answer is “only the first part, silently,” the boundary is wrong. Read the owning contract whole; bound foreign context visibly.&lt;/p&gt;

&lt;p&gt;APC keeps the contract portable. APX applies it in a live runtime without pretending every source of context has the same ownership or budget.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why APX Rejects Invalid Agent Autonomy Instead of Guessing</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Wed, 30 Sep 2026 12:03:19 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/why-apx-rejects-invalid-agent-autonomy-instead-of-guessing-k04</link>
      <guid>https://dev.to/agentprojectcontext/why-apx-rejects-invalid-agent-autonomy-instead-of-guessing-k04</guid>
      <description>&lt;p&gt;An agent autonomy setting looks like small metadata. It is not. It can decide whether a tool runs now or pauses for a human. That makes guessing the wrong response to invalid input.&lt;/p&gt;

&lt;p&gt;APC provides portable project context: agent files, roles, skills, and project metadata travel with the repository. APX is the local runtime that reads that context, runs agents, and enforces tool permissions on the machine. The boundary matters here: a portable agent declaration may request an autonomy mode, but APX must turn that declaration into a real, local permission decision.&lt;/p&gt;

&lt;p&gt;APX has three permission modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;total&lt;/code&gt;: tools run without confirmation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;automatico&lt;/code&gt;: safe work can proceed; destructive, outbound, runtime, MCP, and filesystem-mutating work can require confirmation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;permiso&lt;/code&gt;: only &lt;code&gt;allowed_tools&lt;/code&gt; run directly; every other tool asks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A project has a baseline mode in its runtime configuration. An individual agent can declare &lt;code&gt;Autonomy:&lt;/code&gt; to override that baseline for its own turn. An agent with no declaration inherits the project setting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The bad shortcut
&lt;/h2&gt;

&lt;p&gt;Imagine a project whose normal setting is &lt;code&gt;automatico&lt;/code&gt;, and a review agent should be more constrained:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;reviewer&lt;/span&gt;
&lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Review pull requests&lt;/span&gt;
&lt;span class="na"&gt;Autonomy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;permiso&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine someone edits the card and writes &lt;code&gt;Autonomy: permissive&lt;/code&gt;. A permissive parser might map that to &lt;code&gt;total&lt;/code&gt;, choose the nearest known word, or silently save a value that later means something else. Each path turns a typo into an authorization decision.&lt;/p&gt;

&lt;p&gt;APX does not invent a mode. When it reads a stored autonomy field, an unrecognized value is dropped and the agent inherits the project baseline. That protects the runtime from treating garbage as a new, wider permission setting. It also keeps the effective policy explainable: either a recognized agent override applies, or the project policy applies.&lt;/p&gt;

&lt;p&gt;There is an important nuance. Inheritance is not a substitute for validation. If the project baseline is broader than the author intended for that agent, a malformed stored value will not magically preserve the intended restriction. That is why APX handles direct CLI input differently: &lt;code&gt;apx agent ... --autonomy&lt;/code&gt; rejects an invalid value and tells the user the accepted modes, including &lt;code&gt;inherit&lt;/code&gt;. A person at a terminal gets a visible error instead of a plausible-looking success message.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical rule
&lt;/h2&gt;

&lt;p&gt;Use these meanings consistently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;no --autonomy flag     keep current agent setting
--autonomy inherit     clear agent override; follow project mode
--autonomy automatico  set explicit agent override
--autonomy permiso     set explicit agent override
--autonomy total       set explicit agent override
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then verify the result in the agent file and test an action that should pause. Configuration text alone is not evidence that the tool loop uses it. APX applies a valid agent override to the active turn configuration before its permission guard and risk handling run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the contract small
&lt;/h2&gt;

&lt;p&gt;The portable side should say who the agent is and, when useful, its intended operating boundary. The runtime side must decide what the current machine can actually execute, prompt on, or deny. APC does not become a hidden authorization database; APX does not treat a typo as authority.&lt;/p&gt;

&lt;p&gt;That division makes agent behavior safer to review. A teammate can inspect the declared agent contract in the repository. The local runtime can enforce it without copying private runtime state back into APC. And when an autonomy value is wrong, the system has one honest answer: stop guessing and fix the value.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Portable Agent Contract Cannot Link to a Local Plan</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Tue, 29 Sep 2026 21:45:16 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/a-portable-agent-contract-cannot-link-to-a-local-plan-1ff9</link>
      <guid>https://dev.to/agentprojectcontext/a-portable-agent-contract-cannot-link-to-a-local-plan-1ff9</guid>
      <description>&lt;h1&gt;
  
  
  A Portable Agent Contract Cannot Link to a Local Plan
&lt;/h1&gt;

&lt;p&gt;An &lt;code&gt;AGENTS.md&lt;/code&gt; file can tell every compatible agent how a repository should be handled. That promise breaks when a rule links to a planning file that exists only on one developer's machine. The link works for its author, then becomes a dead end in a fresh clone.&lt;/p&gt;

&lt;p&gt;This is a small boundary, but it is a useful test for portable context. If a future contributor cannot read an instruction and every document it depends on, the instruction is not yet a project contract.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It keeps repository-owned rules, agent definitions, skills, and non-secret MCP expectations in &lt;code&gt;AGENTS.md&lt;/code&gt; and &lt;code&gt;.apc/&lt;/code&gt;. APX is the daily-use runtime and tooling layer. It runs agents and keeps local operational material—sessions, private runtime memory, caches, and machine-specific state—outside the repository.&lt;/p&gt;

&lt;p&gt;A local plan belongs on the APX side of that boundary unless it has been deliberately promoted into a shareable project artifact.&lt;/p&gt;

&lt;h2&gt;
  
  
  A link is an ownership claim
&lt;/h2&gt;

&lt;p&gt;Consider this root instruction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Read &lt;span class="sb"&gt;`spec/release-notes.md`&lt;/span&gt; before changing the deployment flow.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;spec/&lt;/code&gt; is ignored because it holds exploratory notes or raw QA evidence, a new clone has neither the file nor its reasoning. The root contract now asks an agent to follow unavailable context. Worse, a reviewer can miss the error because the author's working tree resolves the link perfectly.&lt;/p&gt;

&lt;p&gt;The same problem appears with absolute paths, private issue exports, temporary design notes, and runtime logs. They may be useful during one task. They cannot be prerequisites for portable behavior.&lt;/p&gt;

&lt;p&gt;Treat every link from &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.apc/&lt;/code&gt;, or tracked documentation as a claim: this target is durable, safe to share, and available to a clean checkout. If that claim is false, change the contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Promote the decision, not the scratchpad
&lt;/h2&gt;

&lt;p&gt;A local plan often contains valuable thinking mixed with temporary material. Do not copy the whole file into APC merely to repair a broken link. Extract the part that survives review.&lt;/p&gt;

&lt;p&gt;For example, a local release investigation might establish one lasting rule: generated assets must be checked before publishing. That rule can live directly in &lt;code&gt;AGENTS.md&lt;/code&gt;, or a concise explanation can become a tracked decision document. The raw command output, incomplete alternatives, and machine paths remain local.&lt;/p&gt;

&lt;p&gt;A practical promotion flow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Keep the working plan and raw evidence local while the task is active.&lt;/li&gt;
&lt;li&gt;Identify the decision that future contributors actually need.&lt;/li&gt;
&lt;li&gt;Rewrite it as a short, self-contained project rule or tracked document.&lt;/li&gt;
&lt;li&gt;Link only to that tracked artifact from APC context.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This gives a clean clone enough guidance to act without importing private or stale task history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the smallest durable surface
&lt;/h2&gt;

&lt;p&gt;Not every note needs a new document. A repository-wide instruction belongs in &lt;code&gt;AGENTS.md&lt;/code&gt;. A reusable procedure can become an APC skill. A rule for only one folder belongs in &lt;code&gt;.apc/rules/&lt;/code&gt;. A longer, reviewable rationale can live in ordinary tracked project documentation.&lt;/p&gt;

&lt;p&gt;The important part is not the filename. It is whether the content remains true, readable, and useful beyond the machine that produced it.&lt;/p&gt;

&lt;p&gt;APX helps keep the other category useful without pretending it is portable. Its local runtime can retain sessions, messages, task state, and private working material under its own storage. That lets an active task keep detail without leaking that detail into the repository contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fresh-clone test
&lt;/h2&gt;

&lt;p&gt;Before adding a context link, ask one question: would this still help an agent that cloned the repository today on another machine?&lt;/p&gt;

&lt;p&gt;If yes, keep it tracked and make the target self-contained. If no, leave it in the local plan or runtime state, then promote only the verified conclusion when it becomes a real project constraint.&lt;/p&gt;

&lt;p&gt;Portable context is not a directory full of references. It is a contract that can stand on its own. APC carries that contract; APX carries the local work around it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Why I Made APX Confirmations Refuse a Group Vote</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Mon, 28 Sep 2026 13:03:32 +0000</pubDate>
      <link>https://dev.to/tecnomanu/why-i-made-apx-confirmations-refuse-a-group-vote-35jd</link>
      <guid>https://dev.to/tecnomanu/why-i-made-apx-confirmations-refuse-a-group-vote-35jd</guid>
      <description>&lt;p&gt;When I added confirmation prompts to APX, the obvious implementation was almost enough: show &lt;strong&gt;Yes&lt;/strong&gt; and &lt;strong&gt;No&lt;/strong&gt;, wait for a callback, then continue the tool call.&lt;/p&gt;

&lt;p&gt;That works in a direct chat. It fails in a group.&lt;/p&gt;

&lt;p&gt;A confirmation message can be visible to several people, but visibility is not authority. If one person asks an agent to send a quote, create a file, or perform another gated action, a nearby button must not let a bystander authorize it. The hard part was not making a button. It was preserving the identity behind the request.&lt;/p&gt;

&lt;p&gt;My thesis is simple: &lt;strong&gt;a confirmation should belong to the person who initiated the action, not to the chat where the button happens to appear.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The tempting shortcut
&lt;/h2&gt;

&lt;p&gt;A Telegram confirmation is asynchronous. An agent is midway through a tool call, decides that an action needs approval, sends an inline keyboard, and waits. Later, Telegram delivers a callback query when somebody taps a button.&lt;/p&gt;

&lt;p&gt;The shortcut is to store only a random confirmation ID and resolve it when any matching callback arrives. It is concise, and it looks correct in a one-person conversation. In a group, it silently changes the question from “did the initiator approve?” to “did anyone with access to the chat press Yes?”&lt;/p&gt;

&lt;p&gt;Those are not equivalent questions.&lt;/p&gt;

&lt;p&gt;The second question is especially dangerous because the interface gives it an air of legitimacy. Everyone sees the same card. Everyone can reach the same button. Without an explicit actor check, a colleague trying to help, a curious participant, or the wrong person tapping by mistake can turn someone else’s request into an authorized action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bind the pending request to an actor
&lt;/h2&gt;

&lt;p&gt;APX keeps pending confirmations in memory. Each entry has a correlation ID, a promise waiting for a boolean answer, an expiry timer, and optionally a &lt;code&gt;guardActorId&lt;/code&gt;. Telegram passes the ID of the person who started the turn as that guard.&lt;/p&gt;

&lt;p&gt;When a callback arrives, APX checks the presser before it resolves anything:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;confirmation belongs to initiator 111
bystander 999 taps Yes
→ reject callback
→ keep confirmation pending
initiator 111 taps Yes
→ resolve confirmation
→ tool may execute
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The detail I care about most is the middle line: rejection does &lt;strong&gt;not&lt;/strong&gt; consume the request. The bystander gets a “Not your confirmation” response, but the original person can still decide. A failed authorization attempt is not the same thing as a decline.&lt;/p&gt;

&lt;p&gt;That distinction keeps the state machine small and truthful. There are three outcomes that matter: approved by the right actor, declined by the right actor, or still waiting. “Someone else pressed a button” belongs outside that set.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make silence safe
&lt;/h2&gt;

&lt;p&gt;A confirmation cannot wait forever. An agent loop suspended forever is not safer; it is merely harder to reason about. APX gives Telegram confirmations a 60-second lifetime. If nobody answers, the promise resolves to &lt;code&gt;false&lt;/code&gt;. The tool does not run.&lt;/p&gt;

&lt;p&gt;This is deliberate. A missing answer should never become permission through a retry, a timeout handler, or a later reconnect. Defaulting to cancellation makes the system’s behavior legible: no explicit approval, no action.&lt;/p&gt;

&lt;p&gt;The same rule matters after a restart. Pending confirmations live only in the daemon process because the agent turn that created them lives there too. If APX restarts, there is no valid suspended turn to resume. A later tap on the old button is shown as expired rather than treated as a fresh approval.&lt;/p&gt;

&lt;p&gt;I prefer that small inconvenience to reviving an action after its surrounding context has disappeared. A quote request might have been edited, a file operation might no longer be relevant, and the person who asked might have changed their mind. An expired button says exactly what happened: this decision window is gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confirmation still is not execution
&lt;/h2&gt;

&lt;p&gt;There is another boundary worth keeping explicit. A successful confirmation means the gate is open; it does not prove that the tool succeeded. The handler still has to run, and it can still fail. Conversely, a declined or expired confirmation means the handler never ran.&lt;/p&gt;

&lt;p&gt;APX tests that separation. Its security-risk tests assert that a declined confirmation leaves the tool’s execution count at zero. The actor-guard test asserts that a different user cannot resolve a guarded confirmation, while the original initiator still can. These are boring tests, but that is exactly the point: a safety promise should be precise enough to test without interpretation.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I learned building it
&lt;/h2&gt;

&lt;p&gt;I used to think of confirmation as a UI feature. It is really a small authorization protocol crossing time and a chat transport. It needs an identity, a one-time correlation key, an expiration rule, and a clear answer for stale state.&lt;/p&gt;

&lt;p&gt;The practical checklist I now use is short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bind approval to an actor when the transport is shared.&lt;/li&gt;
&lt;li&gt;Reject unauthorized responses without destroying the real request.&lt;/li&gt;
&lt;li&gt;Treat no answer as cancellation.&lt;/li&gt;
&lt;li&gt;Treat post-restart buttons as expired.&lt;/li&gt;
&lt;li&gt;Never report a request as pending when the current surface cannot actually ask.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last point matters outside Telegram too. Some APX surfaces have a confirmation adapter; some execution contexts do not. Where APX cannot present a real confirmation, it refuses the action and says that no request was sent. Pretending otherwise would turn a missing capability into a false promise.&lt;/p&gt;

&lt;p&gt;Agents become useful when they can act. They stay trustworthy when every boundary around that action remains explicit. A group chat is a shared place, not shared authority—and a confirmation button should make that true in code, not just in the copy around it.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>security</category>
    </item>
    <item>
      <title>A WhatsApp Capability Should Capture, Not Execute</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Mon, 28 Sep 2026 12:03:50 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/a-whatsapp-capability-should-capture-not-execute-oml</link>
      <guid>https://dev.to/agentprojectcontext/a-whatsapp-capability-should-capture-not-execute-oml</guid>
      <description>&lt;h1&gt;
  
  
  A WhatsApp Capability Should Capture, Not Execute
&lt;/h1&gt;

&lt;p&gt;A contact asks a WhatsApp agent for an appointment. The dangerous interpretation is: the agent now has permission to book one. APX uses a narrower interpretation: the agent may capture the request for its owner to confirm.&lt;/p&gt;

&lt;p&gt;That difference keeps a conversational convenience from quietly becoming an execution path.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. It keeps durable project material in the repository: &lt;code&gt;AGENTS.md&lt;/code&gt;, &lt;code&gt;.apc/&lt;/code&gt;, agent definitions, skills, commands, and MCP hints. APX is the daily-use runtime and tooling layer. It handles local channels, runtime state, identity, and the live decisions around an inbound message.&lt;/p&gt;

&lt;p&gt;A WhatsApp request is runtime work. It should not turn into a portable project instruction—or an automatic external action.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capabilities are deliberately small
&lt;/h2&gt;

&lt;p&gt;APX's WhatsApp configuration recognizes three capabilities: &lt;code&gt;appointments&lt;/code&gt;, &lt;code&gt;errands&lt;/code&gt;, and &lt;code&gt;facts&lt;/code&gt;. All start off by default.&lt;/p&gt;

&lt;p&gt;The names can be misleading if read too quickly. They are not tool grants. A non-owner WhatsApp turn has no tools. Enabling &lt;code&gt;appointments&lt;/code&gt; or &lt;code&gt;errands&lt;/code&gt; lets APX extract a request into a pending suggestion; it does not let the conversation book, send, promise, or decide anything.&lt;/p&gt;

&lt;p&gt;The split matters because answering someone and acting for them are different kinds of authority. A natural reply can say, “I’ll pass that along for confirmation.” It must not say a time is agreed, a slot is free, or an errand will happen.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;facts&lt;/code&gt; is the other deliberate boundary. When an owner has written approved facts for a contact, APX may answer from those facts. Anything outside them remains unknown. A friendly contact-specific rule can adjust tone, but it cannot create facts or tools that the runtime did not supply.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capture runs beside the reply
&lt;/h2&gt;

&lt;p&gt;For enabled appointment or errand capture, APX reads the inbound message separately and records a structured pending suggestion. It preserves the sender, request summary, requested work, urgency, and the sender's timing words.&lt;/p&gt;

&lt;p&gt;That last detail is important. If somebody says “tomorrow afternoon,” APX stores those words rather than resolving them into a timestamp. The capture layer is not allowed to make a calendar decision merely because it understood the phrase.&lt;/p&gt;

&lt;p&gt;APX also keeps capture separate from the reply text. Hiding machine-readable request data inside a reply would require stripping it before delivery. A failed strip could expose internal machinery to the contact. With a separate capture pass, the reply stays plain text and a capture failure only loses a suggestion; it does not corrupt the conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical flow
&lt;/h2&gt;

&lt;p&gt;Imagine a plumber writes:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I come by tomorrow afternoon to check the leak?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With appointment capture enabled, APX can create a pending request containing the contact, purpose, and exact timing language. The owner receives something to review. The agent's reply can acknowledge the request and say it will be passed on.&lt;/p&gt;

&lt;p&gt;It cannot confirm the visit. It cannot claim the owner is available. It cannot turn “tomorrow afternoon” into a booking.&lt;/p&gt;

&lt;p&gt;This is less flashy than an agent that acts immediately, but it is more truthful. The system knows it has captured intent, not completed the work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why APC stays out of it
&lt;/h2&gt;

&lt;p&gt;The project may travel between repositories, machines, and compatible tools. WhatsApp contacts, owner approval, pending requests, and channel-specific capabilities should not travel with it as committed project truth. They depend on a particular account, operator, and moment.&lt;/p&gt;

&lt;p&gt;So APC describes what the project is. APX handles what a local messaging surface may safely do today.&lt;/p&gt;

&lt;p&gt;The useful rule is simple: when a message asks for real-world action, first capture intent. Then let a responsible human—or an explicitly authorized execution path—confirm the action.&lt;/p&gt;

&lt;p&gt;A channel capability should make a request visible. It should not silently make that request true.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Conversation ID Is Not Project Context</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Sun, 27 Sep 2026 12:02:59 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/a-conversation-id-is-not-project-context-1g51</link>
      <guid>https://dev.to/agentprojectcontext/a-conversation-id-is-not-project-context-1g51</guid>
      <description>&lt;h1&gt;
  
  
  A Conversation ID Is Not Project Context
&lt;/h1&gt;

&lt;p&gt;A conversation ID can feel like the fastest way to give an agent continuity: save it in the repository, pass it to the next machine, and resume where the last prompt stopped. It is also the wrong boundary. A conversation is runtime state. Project context is a contract. They should not be stored together.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer. Its &lt;code&gt;AGENTS.md&lt;/code&gt; and &lt;code&gt;.apc/&lt;/code&gt; tree describe the project: agent roles, reusable skills, project metadata, and MCP hints without credentials. APX is the daily-use runtime and tooling layer. It runs agents and keeps the local operational record: sessions, conversations, messages, caches, and task logs.&lt;/p&gt;

&lt;p&gt;That split is not a limitation. It makes a clone predictable.&lt;/p&gt;

&lt;h2&gt;
  
  
  A conversation belongs to one local runtime
&lt;/h2&gt;

&lt;p&gt;When APX registers a project, its committed definition remains in the repository. Its runtime data lives under &lt;code&gt;~/.apx/projects/&amp;lt;apx_id&amp;gt;/&lt;/code&gt;. Per-agent folders include &lt;code&gt;sessions/&lt;/code&gt; and &lt;code&gt;conversations/&lt;/code&gt;; those files reflect a particular machine, engine, account, model context window, and moment in time.&lt;/p&gt;

&lt;p&gt;A saved conversation ID may depend on all of those conditions. Another machine might not have the underlying conversation, might use a different runtime, or might not have permission to read it. Committing the ID makes the repository imply a guarantee it cannot provide.&lt;/p&gt;

&lt;p&gt;The same mistake appears in a subtler form: copying a raw transcript into &lt;code&gt;AGENTS.md&lt;/code&gt; or &lt;code&gt;.apc/memory.md&lt;/code&gt; so the next agent can “continue.” Raw turns include temporary questions, stale tool output, and often sensitive operational detail. They grow quickly while teaching future agents what happened once, rather than what must remain true.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the durable decision, not the handle
&lt;/h2&gt;

&lt;p&gt;Suppose an agent investigated a deployment failure and found a durable rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The deploy command needs a clean generated-assets directory; run the project check before publishing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That rule can become a reviewed project instruction or a concise curated memory fact. It can travel in APC because it explains an ongoing constraint. The conversation ID that led to it should remain local to APX, where an operator can inspect or summarize it when needed.&lt;/p&gt;

&lt;p&gt;The resulting workflow is small:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run work through APX; it records the local session and conversation.&lt;/li&gt;
&lt;li&gt;Extract only stable, reviewable decisions.&lt;/li&gt;
&lt;li&gt;Add those decisions to APC-owned instructions when they apply to the project.&lt;/li&gt;
&lt;li&gt;Let a new machine register the repository and start a new local runtime history.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For a short-lived task, the durable output may be nothing. That is healthy. Not every discussion earns a permanent place in project context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Portability needs a clean restart point
&lt;/h2&gt;

&lt;p&gt;A clone should be able to answer: Which agents exist? Which rules apply? Which skills can run? Which project ID connects this repository to local APX state? APC provides those answers without importing one machine’s chat history.&lt;/p&gt;

&lt;p&gt;APX then supplies the operational continuity appropriate to that machine: &lt;code&gt;apx conversations list&lt;/code&gt; can inspect stored conversations, and &lt;code&gt;apx session summary &amp;lt;id&amp;gt;&lt;/code&gt; can turn a completed session into a concise explanation. Those are runtime tools, not repository format requirements.&lt;/p&gt;

&lt;p&gt;This separation also makes cleanup safer. Removing local runtime state does not erase repository rules. Sharing a repository does not publish chat transcripts. Switching from one supported runtime to another does not require pretending that an opaque conversation handle is a portable artifact.&lt;/p&gt;

&lt;p&gt;Use APC to preserve what collaborators need to know before work begins. Use APX to retain the local evidence of work already done. A conversation ID can help one runtime resume a thread; it should never become the project’s memory contract.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Routine Result Is Not a Delivery</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Sat, 26 Sep 2026 22:16:39 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/a-routine-result-is-not-a-delivery-1dj5</link>
      <guid>https://dev.to/agentprojectcontext/a-routine-result-is-not-a-delivery-1dj5</guid>
      <description>&lt;h1&gt;
  
  
  A Routine Result Is Not a Delivery
&lt;/h1&gt;

&lt;p&gt;A scheduled agent can finish its work and still fail the person who asked for it. The model produced text. The shell command exited. The routine history says it ran. But its result never reached a human.&lt;/p&gt;

&lt;p&gt;That is why APX treats routine output and routine delivery as separate steps. A result is what the routine produced. Delivery is where that result actually goes—and whether that route accepted it.&lt;/p&gt;

&lt;p&gt;APC is the portable context layer: repository-owned rules, agent definitions, and skills that travel with a project. APX is the daily-use runtime and tooling layer. It runs a scheduled job, chooses its local delivery channels, and records the operational outcome. This is runtime behavior, so it belongs in APX, not in APC.&lt;/p&gt;

&lt;h2&gt;
  
  
  Delivery is opt-in
&lt;/h2&gt;

&lt;p&gt;APX resolves delivery in a deliberate order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The routine's own &lt;code&gt;deliver_to&lt;/code&gt; setting.&lt;/li&gt;
&lt;li&gt;The runtime default at &lt;code&gt;config.routines.deliver_to&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;No delivery.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That final default is intentional. A newly introduced delivery feature should not change where older routines send output. A routine must opt in before its result becomes a message on a channel.&lt;/p&gt;

&lt;p&gt;For example, a routine can calculate a daily status and produce a useful answer. Without a configured delivery target, it has completed computation—not communication. The distinction prevents a misleading green checkmark.&lt;/p&gt;

&lt;h2&gt;
  
  
  One output, one owner
&lt;/h2&gt;

&lt;p&gt;A second failure mode is double delivery. A routine can send a Telegram message itself, run a &lt;code&gt;post_commands&lt;/code&gt; shell hook that sends the same text, and also have configured delivery. One logical report then becomes several notifications.&lt;/p&gt;

&lt;p&gt;APX checks for channels already served by the routine handler, its post-command sinks, or an agent tool call. It suppresses the redundant path rather than assuming every configured route should fire.&lt;/p&gt;

&lt;p&gt;This changes how to design a routine. Pick one delivery owner for each channel:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"exec_agent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"spec"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"no_tools"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prompt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Summarize today's status in one short paragraph."&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"deliver_to"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"telegram"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The routine creates the text; configured delivery owns the Telegram send. Alternatively, a hand-written &lt;code&gt;apx telegram send "$APX_LLM_OUTPUT"&lt;/code&gt; post-command can own that send. Do not configure both as independent paths for the same message.&lt;/p&gt;

&lt;h2&gt;
  
  
  A failed route should look failed
&lt;/h2&gt;

&lt;p&gt;APX records a result for each delivery channel: &lt;code&gt;ok&lt;/code&gt;, &lt;code&gt;held&lt;/code&gt;, or &lt;code&gt;error&lt;/code&gt;. An unknown channel is reported as an error rather than silently ignored. If delivery was requested but no channel accepted the message—and no earlier path already served it—the routine ends in an error state with a direct explanation: it produced an answer and no one received it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;held&lt;/code&gt; is different from failure. It means an interruption or notification budget deliberately withheld the message. The result remains available in the run log and routine memory instead of being discarded or mislabeled as sent.&lt;/p&gt;

&lt;p&gt;That distinction is useful operationally:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ok&lt;/code&gt;: result reached configured channel.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;held&lt;/code&gt;: runtime deliberately delayed or withheld a notification.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;error&lt;/code&gt;: route did not accept delivery; investigate configuration or service state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Ordinary reports need less noise
&lt;/h2&gt;

&lt;p&gt;For ordinary Telegram-bound routine reports, APX can record a pending delivery first. The daemon gives the owner a short grace period to open the agent chat and reply. If that happens, the delivery becomes answered and the extra notification is canceled. If it remains pending, a later sweep notifies the owner. Priority or anchor deliveries notify immediately.&lt;/p&gt;

&lt;p&gt;This is a small product rule with a practical effect: a user who already saw the report does not receive an unnecessary second ping, while an unseen report does not vanish inside a routine log.&lt;/p&gt;

&lt;p&gt;The useful test for a scheduled agent is therefore not only “did it run?” Ask:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Did it produce the intended result?&lt;/li&gt;
&lt;li&gt;Which channel owned delivery?&lt;/li&gt;
&lt;li&gt;Was that channel &lt;code&gt;ok&lt;/code&gt;, &lt;code&gt;held&lt;/code&gt;, or &lt;code&gt;error&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Could another path have sent the same report twice?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let APC carry the portable instructions that define the work. Let APX own the local execution and delivery record. A routine becomes useful only when its result reaches the right person exactly once.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>A Routine Name Is Not Its Memory Key</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Fri, 25 Sep 2026 12:02:14 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/a-routine-name-is-not-its-memory-key-25j8</link>
      <guid>https://dev.to/agentprojectcontext/a-routine-name-is-not-its-memory-key-25j8</guid>
      <description>&lt;h1&gt;
  
  
  A Routine Name Is Not Its Memory Key
&lt;/h1&gt;

&lt;p&gt;A scheduled agent task needs two kinds of identity. One is for people: a name such as &lt;code&gt;daily-review&lt;/code&gt;. The other is for stored runtime state: a stable identifier that survives normal edits. Treating those as the same thing creates a subtle failure: edit a routine, and its history silently becomes someone else's problem.&lt;/p&gt;

&lt;p&gt;APC and APX divide this responsibility deliberately. APC is the portable context layer: versioned rules, agent definitions, skills, and other project facts that can travel with a repository. APX is the daily-use runtime and tooling layer. It runs routines and keeps their local operational state outside the repository.&lt;/p&gt;

&lt;p&gt;That division makes routine identity an APX concern.&lt;/p&gt;

&lt;h2&gt;
  
  
  Display names change; runtime state should not
&lt;/h2&gt;

&lt;p&gt;In APX, a routine record has a human-readable &lt;code&gt;name&lt;/code&gt; and a generated &lt;code&gt;id&lt;/code&gt;. The name is how the CLI and a person find the routine. The ID is what APX uses for the routine's private memory path:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.apx/projects/&amp;lt;project-id&amp;gt;/routines/&amp;lt;routine-id&amp;gt;/memory.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is more than implementation detail. Routine memory can hold short, durable operational notes that help the next run. If an ordinary edit assigned a new identity, the routine would no longer read its old notes. The old directory would remain behind, and the newly edited routine would start with an empty memory as if it were new.&lt;/p&gt;

&lt;p&gt;APX avoids that by carrying the existing ID forward when &lt;code&gt;upsertRoutine&lt;/code&gt; rebuilds a routine record. The record may receive a new schedule, prompt, delivery target, or tool boundary, but its runtime identity remains stable. The same applies to &lt;code&gt;created_at&lt;/code&gt;: editing a routine is not creating a second one.&lt;/p&gt;

&lt;h2&gt;
  
  
  The boundary prevents a common confusion
&lt;/h2&gt;

&lt;p&gt;It can be tempting to put this state in APC because both systems are project-aware. But routine memory answers a runtime question: what should this specific scheduled task remember locally between runs? It is not automatically a team-wide project rule.&lt;/p&gt;

&lt;p&gt;For example, a routine named &lt;code&gt;daily-review&lt;/code&gt; might accumulate a short note about an unresolved local inspection. That note belongs to the APX runtime store. It should not appear in a clone just because someone copied the repository, and it should not become a committed instruction without review.&lt;/p&gt;

&lt;p&gt;If the project eventually needs a durable rule—perhaps a verified deployment constraint—a human can promote that fact into APC through the normal review path. Until then, the local note stays local.&lt;/p&gt;

&lt;p&gt;This boundary also keeps the two systems understandable:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;APC names portable, reviewable project context.&lt;/li&gt;
&lt;li&gt;APX names local execution state and connects it to a live routine.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A practical edit test
&lt;/h2&gt;

&lt;p&gt;When changing a routine, verify more than its visible fields. Ask four questions:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Does the routine still have the same ID?&lt;/li&gt;
&lt;li&gt;Does its existing memory path still resolve?&lt;/li&gt;
&lt;li&gt;Did the edit preserve its creation time and prior run state?&lt;/li&gt;
&lt;li&gt;If the name changes, is that an intentional new routine or a migration with an explicit state decision?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The last question matters because a display name is often the lookup key on a command line, while the runtime ID anchors data that should outlive routine edits. Renaming therefore deserves a deliberate product decision, not an accidental side effect of rewriting a JSON record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep identity boring
&lt;/h2&gt;

&lt;p&gt;Stable identifiers are rarely exciting. Their value appears when a routine changes over weeks: scheduled work keeps its own bounded history, local state does not leak into APC, and a harmless edit does not erase operational continuity.&lt;/p&gt;

&lt;p&gt;Let APC carry portable project truth. Let APX keep routine state local. And when a routine changes, preserve the identity that its memory depends on.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Agent Memory Should Propose Before It Writes</title>
      <dc:creator>Manuel Bruña</dc:creator>
      <pubDate>Thu, 24 Sep 2026 12:03:52 +0000</pubDate>
      <link>https://dev.to/agentprojectcontext/agent-memory-should-propose-before-it-writes-228i</link>
      <guid>https://dev.to/agentprojectcontext/agent-memory-should-propose-before-it-writes-228i</guid>
      <description>&lt;h1&gt;
  
  
  Agent Memory Should Propose Before It Writes
&lt;/h1&gt;

&lt;p&gt;An agent can turn a busy day into a plausible list of facts. That does not mean it should silently rewrite the memory that shapes its next prompt.&lt;/p&gt;

&lt;p&gt;That is why APX makes &lt;code&gt;apx memory consolidate&lt;/code&gt; propose by default. It accepts candidate facts from standard input, evaluates them, and prints what it would keep or skip. Nothing is written until you add &lt;code&gt;--apply&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is a small CLI choice with a larger lesson: memory needs an explicit boundary between suggestion and authority.&lt;/p&gt;

&lt;p&gt;APC is the portable project-context layer: committed agent definitions, rules, skills, and other reviewable project facts. APX is the daily-use runtime and tooling layer. It runs agents, keeps local runtime state, and provides the operational commands around it. The consolidation command belongs on the APX side because it works with runtime notebook memory, not repository context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Candidate facts are not trusted facts
&lt;/h2&gt;

&lt;p&gt;A routine, a model, or a person can send one candidate per line to the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'Use pnpm, never npm'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'The owner may change the deployment plan next week'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'Review API changes before merging'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  apx memory consolidate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important part is what does &lt;em&gt;not&lt;/em&gt; happen: APX does not treat every line as memory. The command proposes a kept set and reports skipped candidates. Its implementation separates distilling candidate text from judging what survives, so the same rules apply whether candidates came from an automated routine or from a human at a terminal.&lt;/p&gt;

&lt;p&gt;That protects against a common failure mode. Runtime activity is full of tentative language, stale details, copied text, and one-off task facts. If every summary automatically became long-term memory, the next prompt would inherit guesses as if they were instructions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Preview is a real safety feature
&lt;/h2&gt;

&lt;p&gt;When the proposed output looks right, write it deliberately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;printf&lt;/span&gt; &lt;span class="s1"&gt;'%s\n'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'Use pnpm, never npm'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s1"&gt;'Review API changes before merging'&lt;/span&gt; | &lt;span class="se"&gt;\&lt;/span&gt;
  apx memory consolidate &lt;span class="nt"&gt;--apply&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The extra flag is not ceremony. Agent memory is injected into future prompts, so changing it changes future behavior. A background job that silently edits what an agent believes about itself can create hard-to-see drift: the job succeeded, but the agent is now operating from an unreviewed premise.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;--apply&lt;/code&gt; makes that change visible at the point of action. It also gives operators a useful review loop: generate candidates, inspect the proposed keep/skip decision, then authorize the write only when the surviving facts deserve repeated prompt space.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the scope honest
&lt;/h2&gt;

&lt;p&gt;This command does not promote notes into APC automatically. APX per-agent memory lives under &lt;code&gt;~/.apx/projects/&amp;lt;apx_id&amp;gt;/agents/&amp;lt;slug&amp;gt;/memory.md&lt;/code&gt;, outside the repository. It is local runtime state. APC still holds the committed project contract, such as &lt;code&gt;.apc/agents/&amp;lt;slug&amp;gt;.md&lt;/code&gt; and other portable context.&lt;/p&gt;

&lt;p&gt;That distinction matters. A local notebook can help an agent work today without claiming that every note belongs in version control or should travel to every clone. If a fact later becomes stable, safe, and useful for the whole project, a human can curate it into APC through the normal review process.&lt;/p&gt;

&lt;p&gt;APX also keeps reversal narrow. &lt;code&gt;apx memory revert&lt;/code&gt; removes entries written by consolidation while leaving hand-written notes alone. That makes experimentation less risky: automated consolidation has a bounded undo path instead of treating the whole notebook as disposable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical rule
&lt;/h2&gt;

&lt;p&gt;Use automated processes to collect and compress candidate facts. Use explicit review and &lt;code&gt;--apply&lt;/code&gt; to grant those facts long-term influence.&lt;/p&gt;

&lt;p&gt;APC keeps portable project truth reviewable. APX makes local runtime memory useful without pretending that every observation is already truth.&lt;/p&gt;

&lt;p&gt;For agent memory, that order matters: propose first, write second.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>opensource</category>
      <category>devtools</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
