<?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: Halil Agin</title>
    <description>The latest articles on DEV Community by Halil Agin (@halilagin).</description>
    <link>https://dev.to/halilagin</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%2F4026145%2Fd6c5d1a6-8586-41bb-9486-2f1ce40dcf50.jpg</url>
      <title>DEV Community: Halil Agin</title>
      <link>https://dev.to/halilagin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/halilagin"/>
    <language>en</language>
    <item>
      <title>The two scariest parts of autonomous agents — runaway loops and exposed APIs</title>
      <dc:creator>Halil Agin</dc:creator>
      <pubDate>Sun, 12 Jul 2026 17:21:54 +0000</pubDate>
      <link>https://dev.to/halilagin/the-two-scariest-parts-of-autonomous-agents-runaway-loops-and-exposed-apis-1ob7</link>
      <guid>https://dev.to/halilagin/the-two-scariest-parts-of-autonomous-agents-runaway-loops-and-exposed-apis-1ob7</guid>
      <description>&lt;p&gt;Everyone I talk to about autonomous agents has the same two fears, and they're both justified:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The loop runs away.&lt;/strong&gt; You give an agent a goal, it starts iterating, and it either burns
your API budget at 3am or cheerfully does the wrong thing forty times in a row.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The access problem.&lt;/strong&gt; For an agent to do real work it needs your &lt;em&gt;internal&lt;/em&gt; APIs — billing,
inventory, the admin service that has no auth story because it was never supposed to leave
localhost. Every "just expose an endpoint" answer makes your security team (rightly) say no.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I've been building &lt;a href="https://rysh.ai" rel="noopener noreferrer"&gt;rysh&lt;/a&gt; — an agentic terminal multiplexer where every pane&lt;br&gt;
can be a shell, an agent, or a chat — and these two fears shaped two features I want to walk&lt;br&gt;
through properly, because I think the &lt;em&gt;mechanics&lt;/em&gt; matter more than the pitch. As always on&lt;br&gt;
dev.to: real commands, and an honest list of what's not done at the end.&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 1 — Loop engineering: autonomy with a leash you define
&lt;/h2&gt;

&lt;p&gt;rysh has saved, reusable automations. You write the goal once, then run it with hard limits:&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="c"&gt;# save a recipe (stored under .rysh/automations/)&lt;/span&gt;
&lt;span class="c"&gt;##auto web save scout "find the pricing page, extract the plan names and prices"&lt;/span&gt;

&lt;span class="c"&gt;# run it — with a leash&lt;/span&gt;
&lt;span class="c"&gt;##auto web run --budget-size 50p --max-duration 10m --takeover-when 80 scout&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things are going on there, and each one exists because of a real failure mode:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hard budgets, not vibes.&lt;/strong&gt; &lt;code&gt;--budget-size&lt;/code&gt;, &lt;code&gt;--max-iterations&lt;/code&gt;, and &lt;code&gt;--max-duration&lt;/code&gt; are&lt;br&gt;
ceilings, not suggestions — when a ceiling is hit, the loop stops. Budgets are measured in&lt;br&gt;
context tokens with units I'm unreasonably fond of: &lt;strong&gt;pages, books, and shelves&lt;/strong&gt;. A page is&lt;br&gt;
1,000 tokens, a book is 200 pages, a shelf is 20 books — so &lt;code&gt;--budget-size 50p&lt;/code&gt; is a 50k-token&lt;br&gt;
run and &lt;code&gt;3b&lt;/code&gt; (the default) is 600k. "How much should this cost?" becomes a number you set,&lt;br&gt;
not a surprise you discover. There's also &lt;code&gt;--passes N&lt;/code&gt; for fixed-round runs, &lt;code&gt;--while-duration&lt;/code&gt;&lt;br&gt;
/ &lt;code&gt;--while-budget&lt;/code&gt; for open-ended-but-bounded work, and &lt;code&gt;--dry-run&lt;/code&gt; to see what a recipe&lt;br&gt;
&lt;em&gt;would&lt;/em&gt; do before it does it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;LLM-judged loop conditions.&lt;/strong&gt; The loop doesn't just count iterations — after each pass, a&lt;br&gt;
judge step evaluates whether the goal is actually met. "Run until the tests pass" means&lt;br&gt;
something; "run 10 times and hope" doesn't.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Graceful takeover, not a wall.&lt;/strong&gt; &lt;code&gt;--takeover-when 80&lt;/code&gt; means: when 80% of any ceiling is&lt;br&gt;
consumed, the run switches to a &lt;strong&gt;takeover leg&lt;/strong&gt; — a wrap-up prompt you wrote (in the recipe's&lt;br&gt;
&lt;code&gt;takeover_prompt&lt;/code&gt;) takes over the &lt;em&gt;remaining&lt;/em&gt; budget to finish cleanly: save partial results,&lt;br&gt;
report what's missing, print where it stopped. The agent lands the plane instead of hitting a&lt;br&gt;
wall mid-task. (Plain-language guardrails — "stop on any login wall or rate limit" — live in&lt;br&gt;
the recipe prompt itself, where the agent obeys them per-step.)&lt;/p&gt;

&lt;p&gt;The same engine fans out and schedules:&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="c"&gt;# run one recipe across a list&lt;/span&gt;
&lt;span class="c"&gt;##auto web run --each "site-a.com,site-b.com,site-c.com" scout&lt;/span&gt;

&lt;span class="c"&gt;# put it on a schedule — cron can fire ANY rysh input: prompts, @agent calls, shell, automations&lt;/span&gt;
&lt;span class="c"&gt;##cron add nightly-scout "0 2 * * *" --pane scout-pane --mode rysh "##auto web run scout"&lt;/span&gt;
&lt;span class="c"&gt;##cron next     # when does it fire?&lt;/span&gt;
&lt;span class="c"&gt;##cron logs     # what happened last night?&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And because interruptions happen, automations (and agents generally) checkpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;@@researcher stop        &lt;span class="c"&gt;# interrupt mid-run — state is preserved&lt;/span&gt;
@@researcher &lt;span class="k"&gt;continue&lt;/span&gt;    &lt;span class="c"&gt;# resume from the checkpoint, not from zero&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Recipes are files (this is where loop engineering gets real)
&lt;/h2&gt;

&lt;p&gt;The one-liner &lt;code&gt;save&lt;/code&gt; is just the front door. A recipe is a &lt;strong&gt;markdown file with YAML&lt;br&gt;
frontmatter&lt;/strong&gt; under &lt;code&gt;.rysh/automations/&lt;/code&gt; — versionable, reviewable, PR-able like everything&lt;br&gt;
else in your repo. Here's a real one from my own setup (lightly trimmed): a scout that&lt;br&gt;
browses Instagram for podcast-guest candidates on a topic, discovery-only, and saves a&lt;br&gt;
shortlist to a results folder.&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="c1"&gt;# .rysh/automations/webs/guest-scout.md&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Discover potential podcast guests on Instagram, scoped to a topic.&lt;/span&gt;
  &lt;span class="s"&gt;Discovery-only (never messages/follows/likes); saves a reviewed shortlist.&lt;/span&gt;
&lt;span class="na"&gt;web_profile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ig-podcast&lt;/span&gt;        &lt;span class="c1"&gt;# persistent, pre-authenticated browser profile&lt;/span&gt;
&lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://www.instagram.com/&lt;/span&gt;
&lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;topic&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;                  &lt;span class="c1"&gt;# run as: ##auto web run guest-scout tango&lt;/span&gt;
&lt;span class="na"&gt;output_dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;guest-scout/results&lt;/span&gt;
&lt;span class="na"&gt;loop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;do&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                          &lt;span class="c1"&gt;# the INNER loop — one working session&lt;/span&gt;
    &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
    &lt;span class="na"&gt;max_iterations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300&lt;/span&gt;
    &lt;span class="na"&gt;max_duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;7m&lt;/span&gt;
    &lt;span class="na"&gt;auto_continue&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;budget&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;3b&lt;/span&gt;                 &lt;span class="c1"&gt;# 3 "books" = 600k tokens, hard ceiling&lt;/span&gt;
      &lt;span class="na"&gt;watch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;takeover_when&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;90&lt;/span&gt;      &lt;span class="c1"&gt;# at 90% consumed, switch to the wrap-up leg&lt;/span&gt;
        &lt;span class="na"&gt;takeover_prompt&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="s"&gt;The discovery budget is used up — stop browsing now. Save the&lt;/span&gt;
          &lt;span class="s"&gt;shortlist as-is, mark it PARTIAL at the top, print the file path&lt;/span&gt;
          &lt;span class="s"&gt;and what to cover next time.&lt;/span&gt;
  &lt;span class="na"&gt;while&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;                       &lt;span class="c1"&gt;# the OUTER loop — repeat sessions until the GOAL holds&lt;/span&gt;
    &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;max_iterations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
    &lt;span class="na"&gt;max_duration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;40m&lt;/span&gt;
    &lt;span class="na"&gt;budget&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;15b&lt;/span&gt;
    &lt;span class="na"&gt;prompts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;until&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="s"&gt;The saved shortlist contains at least 12 strong candidates, each with&lt;/span&gt;
        &lt;span class="s"&gt;a handle, a why-they-fit line, and a public contact or an explicit&lt;/span&gt;
        &lt;span class="s"&gt;"on-platform only" note — with no duplicate handles.&lt;/span&gt;
      &lt;span class="na"&gt;iterate_with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="s"&gt;Continue scouting for podcast guests about {{args}}, same rules as&lt;/span&gt;
        &lt;span class="s"&gt;before (discovery only; stop on any login wall or rate limit). The&lt;/span&gt;
        &lt;span class="s"&gt;current shortlist is seeded above: find NEW candidates it is missing,&lt;/span&gt;
        &lt;span class="s"&gt;merge, and save back to the same file.&lt;/span&gt;
&lt;span class="s"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;You are browsing Instagram looking for potential podcast GUESTS about&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="err"&gt;**&lt;/span&gt;&lt;span class="pi"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;}}&lt;/span&gt;&lt;span class="err"&gt;**&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;

&lt;span class="s"&gt;If **{{args}}** is empty, ask me which topic to scout and stop — do not guess.&lt;/span&gt;

&lt;span class="s"&gt;This is **discovery only** — do NOT message, follow, like, or DM. Just read&lt;/span&gt;
&lt;span class="s"&gt;public pages. If you hit a login wall, captcha, or rate-limit notice&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;STOP&lt;/span&gt;
&lt;span class="s"&gt;immediately and report it.&lt;/span&gt;

&lt;span class="na"&gt;For each candidate collect&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;handle, why-they-fit, follower count, public&lt;/span&gt;
&lt;span class="s"&gt;contact (or "none"), and one post that makes them relevant. Aim for 8–12.&lt;/span&gt;

&lt;span class="s"&gt;When done, write the list as Markdown to {{output_dir}}/&amp;lt;topic&amp;gt;-&amp;lt;date&amp;gt;.md&lt;/span&gt;
&lt;span class="s"&gt;and print the saved file path here.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Read the &lt;code&gt;loop&lt;/code&gt; block again, because the two-level structure is the whole idea:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;&lt;code&gt;do&lt;/code&gt; loop&lt;/strong&gt; is one bounded working session: step interval, iteration cap, wall-clock
cap, token budget — and at &lt;code&gt;takeover_when: 90&lt;/code&gt; the &lt;code&gt;takeover_prompt&lt;/code&gt; takes the last 10% to
finish gracefully (save partial results, say what's missing).&lt;/li&gt;
&lt;li&gt;The &lt;strong&gt;&lt;code&gt;while&lt;/code&gt; loop&lt;/strong&gt; wraps it: after each session, the &lt;code&gt;until&lt;/code&gt; condition is judged by the
LLM against actual output — &lt;em&gt;"at least 12 candidates, each with a contact, no duplicate
handles"&lt;/em&gt; — and if it doesn't hold, &lt;code&gt;iterate_with&lt;/code&gt; re-enters with the current shortlist
seeded, under its own outer budget (&lt;code&gt;15b&lt;/code&gt;) and iteration cap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the recipe encodes: &lt;em&gt;what to do, when to act, when to stop, how to stop gracefully, what&lt;br&gt;
"done" actually means, and how to continue if it isn't.&lt;/em&gt; That's what I mean by loop&lt;br&gt;
engineering — the loop is data, not code, and every safety property is declared next to the&lt;br&gt;
goal it protects. &lt;code&gt;{{args}}&lt;/code&gt; templating makes one file a family of automations&lt;br&gt;
(&lt;code&gt;##auto web run guest-scout tango&lt;/code&gt; today, &lt;code&gt;guest-scout "science communicators"&lt;/code&gt; tomorrow),&lt;br&gt;
and results land in &lt;code&gt;output_dir&lt;/code&gt; as dated markdown files you can diff.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;##auto&lt;/code&gt; isn't just for browsers — the same save/run/schedule/budget machinery drives &lt;code&gt;task&lt;/code&gt;,&lt;br&gt;
&lt;code&gt;agent&lt;/code&gt;, and &lt;code&gt;code&lt;/code&gt; automations (&lt;code&gt;##auto code&lt;/code&gt; anchors prompts to a project working directory).&lt;br&gt;
Browser automations can run headless (&lt;code&gt;##web headless on&lt;/code&gt;), so this works on a server without&lt;br&gt;
a desktop session.&lt;/p&gt;

&lt;p&gt;The design position: &lt;strong&gt;the interesting engineering in agent loops isn't the loop — it's the&lt;br&gt;
brakes.&lt;/strong&gt; Budgets, judges, takeover predicates, checkpoints. That's what makes "let it run&lt;br&gt;
overnight" a reasonable sentence instead of a horror-story opener.&lt;/p&gt;
&lt;h2&gt;
  
  
  Part 2 — Forge: your private API, callable by agents, never exposed
&lt;/h2&gt;

&lt;p&gt;Now the access problem. Say your team has an internal REST service on &lt;code&gt;localhost:8080&lt;/code&gt; —&lt;br&gt;
or behind your VPN — and you want &lt;em&gt;agents&lt;/em&gt; (yours, or a teammate's in another rysh session)&lt;br&gt;
to call it. The standard options are all bad: expose it publicly behind auth you now have to&lt;br&gt;
harden, hand out credentials to every agent runtime, or don't do it at all.&lt;/p&gt;

&lt;p&gt;Here's the rysh flow. First, turn the spec into tools:&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="c"&gt;##forge add billing ./billing-openapi.yaml&lt;/span&gt;
&lt;span class="c"&gt;##integration enable billing&lt;/span&gt;
&lt;span class="c"&gt;# your agents can now call the billing API as ordinary tools — locally&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Forge ingests the OpenAPI spec and generates governed agent tools, plus a standalone MCP&lt;br&gt;
server, SDKs (Go/Python/TypeScript/Java), and docs. That alone is useful. But here's the part&lt;br&gt;
I haven't seen elsewhere — &lt;strong&gt;share the API to another session's agents without exposing it&lt;/strong&gt;:&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="c"&gt;# you (the API owner):&lt;/span&gt;
&lt;span class="c"&gt;##forge share api billing&lt;/span&gt;

&lt;span class="c"&gt;# your teammate, in their own rysh session:&lt;/span&gt;
&lt;span class="c"&gt;##forge subscribe billing --scope pane&lt;/span&gt;
&lt;span class="c"&gt;# their agent now sees the billing operations as normal tools&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What actually happens when their agent calls one of those tools:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The subscriber side sends only the &lt;strong&gt;operation name + arguments&lt;/strong&gt; over the rysh upstream
(NATS over WebSocket — the same channel used for live pane sharing).&lt;/li&gt;
&lt;li&gt;Your session receives the request, checks it against &lt;strong&gt;your&lt;/strong&gt; allowlist, and — this is the
key part — &lt;strong&gt;executes the real HTTP call locally, from your machine&lt;/strong&gt;, where
&lt;code&gt;localhost:8080&lt;/code&gt; actually resolves.&lt;/li&gt;
&lt;li&gt;The response is &lt;strong&gt;redacted&lt;/strong&gt; (secrets stripped) and sent back as the tool result.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The remote agent never learns the API's address. The API is never bound to a public interface.&lt;br&gt;
No credentials leave your machine. The endpoint stays exactly where it was — behind your&lt;br&gt;
firewall — and requests tunnel through rysh to be executed by the only party that was already&lt;br&gt;
trusted to call it: you.&lt;/p&gt;

&lt;p&gt;The safety posture, because this feature is only as good as its defaults:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Off by default.&lt;/strong&gt; API sharing requires explicit opt-in configuration &lt;em&gt;and&lt;/em&gt; a control-mode
share — you can't leak an API by accident.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default-deny mutations.&lt;/strong&gt; Shared operations are read-only unless you explicitly allowlist
mutating ones. A remote agent can &lt;code&gt;GET /invoices&lt;/code&gt;; it cannot &lt;code&gt;DELETE&lt;/code&gt; anything you didn't
name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forge-origin only.&lt;/strong&gt; Only Forge-generated API tools can enter the shareable set — built-in
tools (bash, file access) provably cannot be shared through this path.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Redaction + rate limits.&lt;/strong&gt; Responses pass through secret redaction before leaving your
session, and the server enforces per-day quotas and rate limits on invocations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This path is end-to-end tested and went through an adversarial security audit before I'd let&lt;br&gt;
anyone use it — I'll happily go deeper on the invariants in the comments.&lt;/p&gt;

&lt;p&gt;Honest scope note: &lt;strong&gt;Forge is OpenAPI-only today.&lt;/strong&gt; gRPC ingest is a stub and there's no&lt;br&gt;
GraphQL runtime. If your API has a spec, this works now; if not, not yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why these two features are the same feature
&lt;/h2&gt;

&lt;p&gt;Both are answers to the same question: &lt;em&gt;how much power can you give an agent while keeping a&lt;br&gt;
human meaningfully in control?&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loops: as much autonomy as you want, &lt;strong&gt;bounded by budgets and takeover legs you wrote&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;APIs: as much access as you grant, &lt;strong&gt;executed only on your machine, read-only by default&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the design thesis behind rysh generally — every tool call visible in the pane, dangerous&lt;br&gt;
actions gated behind approval, secrets redacted before anything leaves your session. Agents you&lt;br&gt;
can trust because you can &lt;em&gt;see&lt;/em&gt; them and &lt;em&gt;bound&lt;/em&gt; them, not because a vendor promised.&lt;/p&gt;

&lt;h2&gt;
  
  
  The stack, briefly
&lt;/h2&gt;

&lt;p&gt;Go; an actor runtime over NATS for all messaging (the tunneling above is "just" the same&lt;br&gt;
actor/subject machinery that powers live pane sharing); Bubble Tea TUI. It runs &lt;strong&gt;on Anthropic&lt;br&gt;
Claude&lt;/strong&gt; — I'm not claiming a better model; the value is the governance and the surfaces around&lt;br&gt;
it. Self-hostable on your own key; the provider layer is pluggable, Claude is the live backend.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's not done (don't believe me if I imply otherwise)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Forge: &lt;strong&gt;OpenAPI only&lt;/strong&gt; — gRPC ingest is a stub, no GraphQL runtime&lt;/li&gt;
&lt;li&gt;WhatsApp / phone humanoid channels (not live)&lt;/li&gt;
&lt;li&gt;Token-by-token streaming in the CLI (responses land on completion)&lt;/li&gt;
&lt;li&gt;Hosted billing is gated on dev, not live&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try it / shape it
&lt;/h2&gt;

&lt;p&gt;Rysh is in &lt;strong&gt;private beta&lt;/strong&gt; — the code isn't public yet. It's self-hostable (you run it on&lt;br&gt;
your own infra with your own Anthropic key), and access right now is through the&lt;br&gt;
&lt;strong&gt;design-partner program&lt;/strong&gt;: free access, a direct line to me, and your feedback sets the&lt;br&gt;
roadmap. If you have one internal API you'd love agents to use safely, or one workflow you&lt;br&gt;
want to run overnight on a leash, that's exactly the conversation I want:&lt;br&gt;
&lt;a href="https://rysh.ai/design-partner" rel="noopener noreferrer"&gt;apply to the design-partner program&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feedback on the tunneling trust model is especially welcome — poke holes in it in the comments.&lt;/p&gt;

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