<?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: Jeshua ben Joseph</title>
    <description>The latest articles on DEV Community by Jeshua ben Joseph (@jeshuabenjoseph).</description>
    <link>https://dev.to/jeshuabenjoseph</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%2F4214099%2Fd8bc1f75-d415-418e-91ce-d4777880fd37.png</url>
      <title>DEV Community: Jeshua ben Joseph</title>
      <link>https://dev.to/jeshuabenjoseph</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jeshuabenjoseph"/>
    <language>en</language>
    <item>
      <title>Connect Claude Code to Carbon Forge over MCP: shared memory your agents can read, write and cite</title>
      <dc:creator>Jeshua ben Joseph</dc:creator>
      <pubDate>Thu, 29 Oct 2026 02:04:27 +0000</pubDate>
      <link>https://dev.to/jeshuabenjoseph/connect-claude-code-to-carbon-forge-over-mcp-shared-memory-your-agents-can-read-write-and-cite-1dep</link>
      <guid>https://dev.to/jeshuabenjoseph/connect-claude-code-to-carbon-forge-over-mcp-shared-memory-your-agents-can-read-write-and-cite-1dep</guid>
      <description>&lt;p&gt;Disclosure: we build Carbon Forge at 100monkeys.ai, so read this as a maker's account. This guide was drafted by one of our AI agents from the public docs at &lt;a href="https://carbonforge.dev/docs/p/home" rel="noopener noreferrer"&gt;carbonforge.dev/docs&lt;/a&gt; and reviewed by the company. The Carbon Forge steps quote the docs; the Claude Code command is from Claude Code's own &lt;code&gt;claude mcp add --help&lt;/code&gt;. Where the docs leave a question open, the last section says so.&lt;/p&gt;

&lt;p&gt;Carbon Forge keeps code, files and prose in one record on the server, and people and agents read and write it through the same tools. This guide attaches Claude Code to that record over MCP.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why connect them
&lt;/h2&gt;

&lt;p&gt;A coding agent forgets between sessions unless its notes live somewhere it can read again. Carbon Forge is that somewhere, shared with the people on the project. The docs call MCP "a primary product surface, co-equal with the human editor, against the same atoms, pages, links, and embeddings" (&lt;a href="https://carbonforge.dev/docs/p/features/shared-cortex-for-llms" rel="noopener noreferrer"&gt;A shared cortex for LLMs&lt;/a&gt;). An agent's page is a page a person can open, correct and link to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1. Try the read-only endpoint with no token
&lt;/h2&gt;

&lt;p&gt;Before you sign up, attach to public content. From &lt;a href="https://carbonforge.dev/docs/p/guides/mcp-anonymous-access" rel="noopener noreferrer"&gt;Reading a public cortex without an account&lt;/a&gt;: "Add the instance's MCP endpoint to your client with no Authorization header. For this instance that is &lt;code&gt;https://carbonforge.dev/api/mcp&lt;/code&gt; over Streamable HTTP. With Claude Code:"&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http cortex-public https://carbonforge.dev/api/mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get twenty-two read-only tools, rate-limited per IP address. Ask Claude Code to read the page &lt;code&gt;home&lt;/code&gt; in the workspace &lt;code&gt;docs&lt;/code&gt;; with no token there is no current workspace, so every call names &lt;code&gt;workspace&lt;/code&gt;. Remove this entry with &lt;code&gt;claude mcp remove cortex-public&lt;/code&gt; before adding the authenticated one, so the agent is not reading two surfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Sign in and pick the workspace
&lt;/h2&gt;

&lt;p&gt;Sign in at &lt;a href="https://carbonforge.dev/login" rel="noopener noreferrer"&gt;carbonforge.dev/login&lt;/a&gt; with an email link or the 100monkeys button; there are no passwords. Public workspaces are free, and every account includes one free private workspace (&lt;a href="https://carbonforge.dev/pricing" rel="noopener noreferrer"&gt;pricing&lt;/a&gt;). Decide which workspace the agent will use as its memory. A private one keeps the notes to members.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Mint a token with the narrowest scope that fits
&lt;/h2&gt;

&lt;p&gt;From &lt;a href="https://carbonforge.dev/docs/p/guides/mcp-tokens" rel="noopener noreferrer"&gt;MCP tokens&lt;/a&gt;: open settings and pick API tokens; choose the workspace and a role cap (viewer, editor or admin); pick a tool-scope; name the token after the agent; copy the secret, which "is shown once, then only the prefix."&lt;/p&gt;

&lt;p&gt;For shared memory, &lt;strong&gt;Basic LLM memory&lt;/strong&gt; lets the agent "read and write pages, atoms and tags, and run search, with basic graph reads", which the docs call "the minimum for an LLM that uses Carbon Forge as its memory." For an agent that only recalls, &lt;strong&gt;Read-only memory&lt;/strong&gt; writes nothing. For code work, &lt;strong&gt;SCM agent&lt;/strong&gt; adds lanes, trees and landing (&lt;a href="https://carbonforge.dev/docs/p/guides/mcp-token-scopes" rel="noopener noreferrer"&gt;MCP token scopes&lt;/a&gt;). A tool outside the scope "answers exactly as a tool that does not exist."&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Add the server to Claude Code with the token
&lt;/h2&gt;

&lt;p&gt;The docs say to point the client at the endpoint "with the token in the Authorization header". Claude Code sets headers with &lt;code&gt;--header&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; http carbon-forge https://carbonforge.dev/api/mcp &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer ‹your token›"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you put the token in an environment variable and write &lt;code&gt;$CARBON_FORGE_TOKEN&lt;/code&gt; instead, your shell expands it before Claude Code sees it, so the secret is still stored in Claude Code's configuration. Treat that configuration as a secret either way, and keep the server in the default &lt;code&gt;local&lt;/code&gt; scope or &lt;code&gt;user&lt;/code&gt; scope rather than a file you commit.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5. Let the agent ground itself
&lt;/h2&gt;

&lt;p&gt;Start a session and ask Claude Code to call &lt;code&gt;cortex.ground&lt;/code&gt;. The docs make it the first call: it "Returns the per-instance README, the calling identity, what the bearer can do, what is reachable, and helper-service health" (&lt;a href="https://carbonforge.dev/docs/p/guides/cortex-ground" rel="noopener noreferrer"&gt;cortex.ground&lt;/a&gt;). The raw call is:&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;"jsonrpc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tools/call"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"params"&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;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cortex.ground"&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="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 server also delivers the same payload on the &lt;code&gt;initialize&lt;/code&gt; handshake and on the first tool call of a session, so an agent that skips this step is still oriented. Read the &lt;code&gt;capabilities&lt;/code&gt; block to confirm the token can write.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6. Write memory, then cite it
&lt;/h2&gt;

&lt;p&gt;Ask the agent to record what it learned as a page, for example a decision and its reason, and to read that page at the start of the next session. Two properties make this memory rather than a cache. Every save writes a revision and nothing rewrites one, so you can read what the agent wrote last week. And "every entity-returning tool decorates the result with a clickable permalink so an LLM can hand a working URL back to its human" (&lt;a href="https://carbonforge.dev/docs/p/architecture/mcp-server" rel="noopener noreferrer"&gt;How MCP works&lt;/a&gt;): ask the agent to cite the permalink of every page it relied on, and check them.&lt;/p&gt;

&lt;p&gt;For code, the same record holds it. An agent opens a lane instead of cloning, and a landing is one changeset, written in one transaction or not at all (&lt;a href="https://carbonforge.dev/docs/p/guides/lanes" rel="noopener noreferrer"&gt;Working in lanes&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7. Watch the audit log and revoke when done
&lt;/h2&gt;

&lt;p&gt;"Every tool call lands in the audit log under the token identity." When the agent no longer needs access, or the token leaks, revoke it from settings; "in-flight calls fail on the next request" (&lt;a href="https://carbonforge.dev/docs/p/guides/mcp-tokens" rel="noopener noreferrer"&gt;MCP tokens&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  What the docs leave unanswered
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The endpoint for an instance on its own host. The anonymous-access page names &lt;code&gt;https://carbonforge.dev/api/mcp&lt;/code&gt; "for this instance"; it does not say which URL to use for an instance at its own subdomain or a vanity domain.&lt;/li&gt;
&lt;li&gt;Two paths. The same page uses &lt;code&gt;/api/mcp&lt;/code&gt;; the curl example on How MCP works posts to &lt;code&gt;/mcp&lt;/code&gt;. We use &lt;code&gt;/api/mcp&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Token lifetime. The docs describe revoking a token but do not state whether a token expires on its own.&lt;/li&gt;
&lt;li&gt;Client-specific configuration. The docs give no Claude Code command; the one above is Claude Code's documented syntax for a header.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Related guides
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://carbonforge.dev/guides/cursor-codex-mcp" rel="noopener noreferrer"&gt;Connect Cursor, Codex and any MCP client to one Carbon Forge workspace&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://100monkeys.ai/blog/ai-agent-traceability-checklist?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=guides-2026-10-28" rel="noopener noreferrer"&gt;A traceability checklist for AI agents in production&lt;/a&gt; (100monkeys.ai)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://100monkeys.ai/blog/install-aegis-on-ubuntu-vps?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=guides-2026-10-28" rel="noopener noreferrer"&gt;Install AEGIS on a fresh Ubuntu VPS and run your first approved task&lt;/a&gt; (100monkeys.ai)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Give Claude Code a record it can cite.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://carbonforge.dev/login" rel="noopener noreferrer"&gt;Start free&lt;/a&gt; · &lt;a href="https://carbonforge.dev/docs/p/home" rel="noopener noreferrer"&gt;Read the docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://carbonforge.dev/guides/claude-code-mcp" rel="noopener noreferrer"&gt;https://carbonforge.dev/guides/claude-code-mcp&lt;/a&gt; . Carbon Forge: &lt;a href="https://carbonforge.dev/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=push-2026-10-28" rel="noopener noreferrer"&gt;https://carbonforge.dev/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=push-2026-10-28&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>mcp</category>
      <category>claude</category>
      <category>devtools</category>
    </item>
    <item>
      <title>Install AEGIS on a fresh Ubuntu VPS and run your first approved task</title>
      <dc:creator>Jeshua ben Joseph</dc:creator>
      <pubDate>Thu, 29 Oct 2026 01:57:42 +0000</pubDate>
      <link>https://dev.to/jeshuabenjoseph/install-aegis-on-a-fresh-ubuntu-vps-and-run-your-first-approved-task-1iga</link>
      <guid>https://dev.to/jeshuabenjoseph/install-aegis-on-a-fresh-ubuntu-vps-and-run-your-first-approved-task-1iga</guid>
      <description>&lt;p&gt;Disclosure: 100monkeys.ai builds AEGIS, so read this guide as a maker's account. It was drafted by one of our AI agents from the public AEGIS documentation at &lt;a href="https://docs.100monkeys.ai/docs/getting-started" rel="noopener noreferrer"&gt;docs.100monkeys.ai&lt;/a&gt; and reviewed by the company. Every command below is copied from those docs or from our home page. We did not run this exact sequence on a fresh VPS for this guide, and where the docs disagree with each other we say so instead of guessing.&lt;/p&gt;

&lt;p&gt;AEGIS by 100monkeys.ai, in beta, is a self-hosted orchestrator that runs autonomous agents in isolated, policy-enforced runtimes with durable state. This guide takes a fresh Ubuntu server to a running local stack, then runs one agent behind a human approval gate, so the agent's work stops and waits until you answer yes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before you start
&lt;/h2&gt;

&lt;p&gt;Know what the quick install is for. The Getting Started page says it plainly: &lt;code&gt;aegis init&lt;/code&gt; "is designed for local testing and evaluation only. It uses an in-memory secrets store and does not deploy Keycloak (IAM) or OpenBao (secrets management)." The Infrastructure Requirements page lists its IAM as "None (unauthenticated)" and its TLS as "None". For production the docs point to the &lt;a href="https://github.com/100monkeys-ai/aegis-deploy" rel="noopener noreferrer"&gt;aegis-deploy&lt;/a&gt; repository instead.&lt;/p&gt;

&lt;p&gt;So on a VPS, treat this stack as a private lab. The CLI's health checks default to host &lt;code&gt;127.0.0.1&lt;/code&gt; and port &lt;code&gt;8088&lt;/code&gt;. Do not open that port to the internet; reach the box over SSH.&lt;/p&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An Ubuntu or Debian server you can reach over SSH with a user that can run &lt;code&gt;sudo&lt;/code&gt;. The installer "runs on Ubuntu or Debian (it needs &lt;code&gt;apt-get&lt;/code&gt;)".&lt;/li&gt;
&lt;li&gt;An x86_64 machine. The release the installer pins carries the Linux x86_64 archive, &lt;code&gt;aegis-linux-x86_64.tar.gz&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An API key for a model provider. The docs' provider page covers OpenAI, Anthropic and Ollama, under the bring-your-own-model alias system.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1. Run the installer
&lt;/h2&gt;

&lt;p&gt;Copy the line from &lt;a href="https://100monkeys.ai/" rel="noopener noreferrer"&gt;100monkeys.ai&lt;/a&gt;, where it is printed, and run it as your normal user:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://get.100monkeys.ai | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the script first if you prefer. The docs say &lt;code&gt;https://get.100monkeys.ai&lt;/code&gt; redirects to &lt;code&gt;install.sh&lt;/code&gt; on the &lt;code&gt;main&lt;/code&gt; branch of &lt;a href="https://github.com/100monkeys-ai/aegis-orchestrator" rel="noopener noreferrer"&gt;aegis-orchestrator&lt;/a&gt;. On Linux it installs &lt;code&gt;curl&lt;/code&gt;, &lt;code&gt;ca-certificates&lt;/code&gt; and &lt;code&gt;fuse3&lt;/code&gt; where missing, installs &lt;code&gt;libfuse3&lt;/code&gt; where the binary needs it, and installs Docker Engine (&lt;code&gt;docker-ce&lt;/code&gt;) when Docker is absent. When Docker runs but your user cannot reach it, it adds you to the &lt;code&gt;docker&lt;/code&gt; group. It then installs &lt;code&gt;aegis&lt;/code&gt; to &lt;code&gt;/usr/local/bin/aegis&lt;/code&gt; and starts the stack with &lt;code&gt;aegis up --tag &amp;lt;version&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To pin a release, set &lt;code&gt;AEGIS_VERSION&lt;/code&gt; to a release tag before running it; the docs list every published package on the Releases page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2. Check the binary and the stack
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aegis &lt;span class="nt"&gt;--version&lt;/span&gt;
aegis status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;aegis status&lt;/code&gt; reports local stack health. If you were added to the &lt;code&gt;docker&lt;/code&gt; group during the install, log out and back in so new shells carry the group.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3. Run the guided setup and choose a model provider
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aegis init
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The wizard "prepares stack files, configures the node, starts Docker Compose services, verifies health, and can optionally load smoke-test agents". Accept the hello-world smoke test when it asks; the next step uses it. The configuration it writes maps the model aliases &lt;code&gt;default&lt;/code&gt;, &lt;code&gt;smart&lt;/code&gt;, &lt;code&gt;judge&lt;/code&gt; and &lt;code&gt;tool-judge&lt;/code&gt; on the provider you choose. The hello-world agent names &lt;code&gt;smart&lt;/code&gt;, and an alias the node does not map fails with &lt;code&gt;Model alias '&amp;lt;alias&amp;gt;' not found&lt;/code&gt;, so finish the provider prompt. Stack files go to &lt;code&gt;~/.aegis&lt;/code&gt; unless you pass &lt;code&gt;--dir&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4. Run hello-world once, unattended
&lt;/h2&gt;

&lt;p&gt;Prove the loop works before you add a gate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aegis task execute hello-world &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; &lt;span class="s1"&gt;'{"task": "Write a Python function that returns the Fibonacci sequence up to n."}'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--follow&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;--follow&lt;/code&gt; streams iteration events. The agent generates code, runs validation, and either succeeds or refines across iterations until its validators pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5. Write a workflow with an approval gate
&lt;/h2&gt;

&lt;p&gt;An approval in AEGIS is a workflow state of &lt;code&gt;kind: Human&lt;/code&gt;. Save this as &lt;code&gt;approved-task.yaml&lt;/code&gt;. It follows the shape of the example on the Building Workflows page, cut down to one agent and one gate:&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="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;100monkeys.ai/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Workflow&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&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;approved-task&lt;/span&gt;
  &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1.0.0"&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;One&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;agent&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;drafts,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;a&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;person&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;approves,&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;then&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;the&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;completes."&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;initial_state&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DRAFT&lt;/span&gt;
  &lt;span class="na"&gt;states&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;DRAFT&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Agent&lt;/span&gt;
      &lt;span class="na"&gt;agent&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hello-world&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;600s&lt;/span&gt;
      &lt;span class="na"&gt;transitions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;on_success&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;APPROVE&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;on_failure&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;FAILED&lt;/span&gt;
    &lt;span class="na"&gt;APPROVE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Human&lt;/span&gt;
      &lt;span class="na"&gt;prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;Draft:&lt;/span&gt;
        &lt;span class="s"&gt;{{DRAFT.output}}&lt;/span&gt;

        &lt;span class="s"&gt;Approve? (yes/no)&lt;/span&gt;
      &lt;span class="na"&gt;timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;86400s&lt;/span&gt;
      &lt;span class="na"&gt;transitions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;input_equals_yes&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;DONE&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;input_equals_no&lt;/span&gt;
          &lt;span class="na"&gt;target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;FAILED&lt;/span&gt;
    &lt;span class="na"&gt;DONE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;System&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;echo&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Approved'"&lt;/span&gt;
      &lt;span class="na"&gt;transitions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
    &lt;span class="na"&gt;FAILED&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;System&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;echo&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;'Rejected&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;or&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;failed'"&lt;/span&gt;
      &lt;span class="na"&gt;transitions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6. Deploy it and start a run
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aegis workflow deploy ./approved-task.yaml &lt;span class="nt"&gt;--force&lt;/span&gt;
aegis workflow run approved-task &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--input&lt;/span&gt; &lt;span class="s1"&gt;'{"task": "Write a Python function that returns the Fibonacci sequence up to n."}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The run command prints an execution id. Watch it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aegis workflow logs &amp;lt;execution-id&amp;gt; --follow --verbose
aegis workflow executions get &amp;lt;execution-id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the draft is done, &lt;code&gt;executions get&lt;/code&gt; shows the current state as &lt;code&gt;APPROVE (WAITING FOR HUMAN SIGNAL)&lt;/code&gt;. Nothing after the gate runs until someone answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 7. Read the draft, then answer
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aegis workflow signal &amp;lt;execution-id&amp;gt; --response yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Answer &lt;code&gt;no&lt;/code&gt; to send the run to &lt;code&gt;FAILED&lt;/code&gt; instead. A gate that nobody answers expires after its timeout; with the default behaviour the run is marked failed with the reason &lt;code&gt;human_input_timeout&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One thing to know: the docs do not agree on the word. The Human Approvals page says a yes-or-no gate takes the responses &lt;code&gt;["yes", "no"]&lt;/code&gt;; the Building Workflows page signals &lt;code&gt;--response approved&lt;/code&gt;; the CLI page shows &lt;code&gt;--response "approve"&lt;/code&gt;. We use &lt;code&gt;yes&lt;/code&gt; because it is what the &lt;code&gt;input_equals_yes&lt;/code&gt; transition is named for. If the run does not move, check &lt;code&gt;executions get&lt;/code&gt; and try the other forms.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this does not cover
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Production. Use aegis-deploy, which adds Keycloak, OpenBao, TLS through Caddy and observability.&lt;/li&gt;
&lt;li&gt;Exposing the API. With no IAM on the &lt;code&gt;aegis init&lt;/code&gt; stack, anyone who reaches port 8088 can act on it.&lt;/li&gt;
&lt;li&gt;Hardware sizing. The docs give a dependency matrix (Docker 24.0+ or Podman 4.0+, PostgreSQL 15+, SeaweedFS, Temporal for workflows) but we did not find a minimum RAM figure for the local stack, so we do not state one.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next
&lt;/h2&gt;

&lt;p&gt;For the reasoning behind the gate, read &lt;a href="https://100monkeys.ai/blog/approval-step-for-an-agent-orchestrator" rel="noopener noreferrer"&gt;How to give an orchestrator an approval step&lt;/a&gt;. For what to record around each run, read &lt;a href="https://100monkeys.ai/blog/ai-agent-traceability-checklist" rel="noopener noreferrer"&gt;A traceability checklist for AI agents in production&lt;/a&gt;. If you want your agents' notes and code in one record they can read and write over MCP, see &lt;a href="https://carbonforge.dev/guides/claude-code-mcp" rel="noopener noreferrer"&gt;Connect Claude Code to Carbon Forge over MCP&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://100monkeys.ai/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=push-2026-10-28" rel="noopener noreferrer"&gt;Install AEGIS from 100monkeys.ai&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://100monkeys.ai/blog/install-aegis-on-ubuntu-vps" rel="noopener noreferrer"&gt;https://100monkeys.ai/blog/install-aegis-on-ubuntu-vps&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>devops</category>
      <category>opensource</category>
      <category>selfhosted</category>
    </item>
    <item>
      <title>The approval is the product: why an agent orchestrator should make you say yes</title>
      <dc:creator>Jeshua ben Joseph</dc:creator>
      <pubDate>Thu, 29 Oct 2026 01:56:22 +0000</pubDate>
      <link>https://dev.to/jeshuabenjoseph/the-approval-is-the-product-why-an-agent-orchestrator-should-make-you-say-yes-2ld4</link>
      <guid>https://dev.to/jeshuabenjoseph/the-approval-is-the-product-why-an-agent-orchestrator-should-make-you-say-yes-2ld4</guid>
      <description>&lt;p&gt;&lt;em&gt;This essay was written by an AI agent of 100monkeys.ai and reviewed for publication by the company. We build AEGIS and Zaru, the two products named in its last section, so read that part as a maker's account.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The usual pitch for an agent platform is about what the agent can do without you. It can open the pull request, answer the ticket, send the follow-up, run overnight. The less you have to touch it, the better it is supposed to be.&lt;/p&gt;

&lt;p&gt;We think that pitch has the value backwards. The useful property of an agent system is not how little it needs you. It is how precisely it lets you decide what it may do, and how reliably it stops at the line you drew. The approval is not friction around the product. For anything that acts in the world on your behalf, the approval is the product.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two kinds of yes
&lt;/h2&gt;

&lt;p&gt;There are two moments at which a person can say yes to an agent.&lt;/p&gt;

&lt;p&gt;The first is in advance. Before the agent runs, someone writes down what it is allowed to touch: which tools, which networks, which files, which secrets. Everything else is refused. This is a yes given once, in a form a machine can enforce and a person can read later.&lt;/p&gt;

&lt;p&gt;The second is at the moment of the act. The agent has prepared something consequential, an email to a stranger, a payment, a deletion, and it stops and waits. A person reads the exact thing about to happen and says yes or no to that one act.&lt;/p&gt;

&lt;p&gt;Most systems offer a weak version of one and skip the other. An allow-list exists but defaults to open. A confirmation exists but appears so often that people click through it, or it appears after the act, as a notification of what already happened. Neither is a yes in any meaningful sense.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the first yes belongs in the runtime
&lt;/h2&gt;

&lt;p&gt;A rule written in a prompt is a request. The model may follow it. Under pressure, under a clever input, or simply under a long enough task, it may not, and nothing outside the model notices.&lt;/p&gt;

&lt;p&gt;A rule written in the runtime is a wall. If the policy says the agent cannot reach a host, the network call fails no matter what the model decides. If the agent is never handed the credential, no prompt can make it leak the credential. This is the difference between limits by promise and limits by architecture, and it is the reason an orchestrator, not a model, is where the first yes should live.&lt;/p&gt;

&lt;p&gt;It is also why the default matters more than any single rule. A deny-by-default policy means the absence of a yes is a no. An allow-by-default policy means every gap in the policy is a permission nobody granted. Agents find gaps quickly, not out of malice but because they try things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why self-hosted
&lt;/h2&gt;

&lt;p&gt;If the runtime holds the first yes, then whoever runs the runtime holds it too. For a hobby project that may not matter. For an agent that touches your source code, your customers or your infrastructure, the person who decides what the agent may do should be someone in your organisation, on machines you control, reading a policy you can audit. Self-hosting is not a deployment preference here. It is where the authority sits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why the second yes must be exact
&lt;/h2&gt;

&lt;p&gt;The second yes fails in a quieter way. If the approval attaches to a description of the act rather than the act itself, the agent can change the act after the yes. If the approval is a general permission ("you may send emails"), it is the first yes again, given carelessly.&lt;/p&gt;

&lt;p&gt;A useful approval at the moment of the act shows the exact thing, binds to that exact thing, and expires if the thing changes. One message, read and approved. Then the next one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Durable, so a yes is not lost
&lt;/h2&gt;

&lt;p&gt;There is a practical requirement under both kinds of yes: the state of the work has to survive. An agent waiting an hour for a person to approve something cannot lose its place when a process restarts. If it does, the system either drops the work, which teaches people to avoid approvals, or retries it from the start, which can repeat acts already done. Waiting for a person is only safe if the waiting is durable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we build for each yes
&lt;/h2&gt;

&lt;p&gt;At 100monkeys.ai we build both sides, and each sentence below is what our public pages or our own measured use states.&lt;/p&gt;

&lt;p&gt;AEGIS by 100monkeys.ai, in beta, holds the first yes. In the words of its home page, "AEGIS is a self-hosted orchestrator that runs autonomous agents in isolated, policy-enforced runtimes with durable FSM state." Its security policy is declarative and deny-by-default. Agent runs are isolated at the kernel level, in micro-VMs or rootless containers. Secrets are held by a keymaster, so agents never see the credentials they use. Tool calls go through SEAL, a cryptographic tool-call protocol. Workflows are durable, so state survives a crash or a restart. It is open source under AGPL-3.0, and it installs with one line copied from its home page:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl -fsSL https://get.100monkeys.ai | bash&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Zaru holds the second yes. It is a personal AI that works alongside its user, remembers them and shows its work, and its memory of the person is theirs to read and edit. Here is what that looks like in our own use: when Zaru's mail tool sends an email for our founder, by default the send does not happen. It answers that approval is pending and waits in Zaru's web app under Approvals until he approves that one message. Zaru is sold by My Zaru, Inc. at myzaru.com.&lt;/p&gt;

&lt;p&gt;Neither of these makes an agent safe on its own. What they do is keep a person in a position to decide, before the run and at the act, and that is the part most agent tooling leaves out.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we would like to hear
&lt;/h2&gt;

&lt;p&gt;If you run agents that act outside a sandbox, we would like to know where your yes lives today: in a prompt, in a policy, or in a person's inbox after the fact. And if you have built an approval step that people do not click through, we would like to learn how.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclosure: 100monkeys.ai builds AEGIS by 100monkeys.ai, an open-source agent orchestrator in beta; Zaru, a companion that asks before it acts; and Carbon Forge, the record people and agents share. This essay was drafted by one of our agents. AEGIS, its docs and the install line are here: &lt;a href="https://100monkeys.ai/?utm_source=devto&amp;amp;utm_medium=article&amp;amp;utm_campaign=push-2026-10-28" rel="noopener noreferrer"&gt;https://100monkeys.ai/&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Originally published at &lt;a href="https://medium.com/@jeshua_46811/the-approval-is-the-product-why-an-agent-orchestrator-should-make-you-say-yes-1f1b2d71af61" rel="noopener noreferrer"&gt;https://medium.com/@jeshua_46811/the-approval-is-the-product-why-an-agent-orchestrator-should-make-you-say-yes-1f1b2d71af61&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>security</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
