<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>Khalid Elborai - takween</title>
    <subtitle>Khalid Elborai — CTO at Buguard, software engineer, and open-source contributor.</subtitle>
    <link rel="self" type="application/atom+xml" href="https://blog.borai.dev/tags/takween/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://blog.borai.dev"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2026-06-08T00:00:00+00:00</updated>
    <id>https://blog.borai.dev/tags/takween/atom.xml</id>
    <entry xml:lang="en">
        <title>Building takween</title>
        <published>2026-06-08T00:00:00+00:00</published>
        <updated>2026-06-08T00:00:00+00:00</updated>
        
        <author>
          <name>
            
              Khalid Elborai
            
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://blog.borai.dev/building-takween/"/>
        <id>https://blog.borai.dev/building-takween/</id>
        
        <content type="html" xml:base="https://blog.borai.dev/building-takween/">&lt;p&gt;Most agent tools ask you to trust them first and find out later. You drop in an API key, point it at your repo, and hope the sandbox holds while it runs whatever the model just decided to run. I work in offensive security, and a lot of what I do is research on AI agents: autonomous pentesters that chase and chain vulnerabilities, and intelligence that watches attack surfaces and the dark web for what&#x27;s already leaking. When an agent like that gets pointed at hostile systems, with real access, &quot;hope the sandbox holds&quot; is how you get breached by your own tool.&lt;&#x2F;p&gt;
&lt;p&gt;So I&#x27;ve spent a while building the agent framework I wish I&#x27;d had for exactly that. It&#x27;s called &lt;strong&gt;takween&lt;&#x2F;strong&gt;, and it started from one rule: never trust the model&#x27;s output.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;what-it-is&quot;&gt;what it is&lt;a class=&quot;post-anchor&quot; href=&quot;#what-it-is&quot; aria-label=&quot;Anchor link for: what-it-is&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;A Rust workspace, 29 crates, that gives you a CLI called &lt;code&gt;tk&lt;&#x2F;code&gt; and an &lt;code&gt;Agent&lt;&#x2F;code&gt; you embed in your own program. It talks to any OpenAI- or Anthropic-wire endpoint, checkpoints as it runs, and ships around 833 tests. Here&#x27;s a small change going from a prompt to a green build:&lt;&#x2F;p&gt;

&lt;div class=&quot;asciinema-cast&quot;
     data-cast=&quot;&#x2F;casts&#x2F;takween.cast&quot; data-poster=&quot;npt:11&quot; data-idle=&quot;1.5&quot;&gt;&lt;&#x2F;div&gt;&lt;script src=&quot;https:&#x2F;&#x2F;blog.borai.dev&#x2F;js&#x2F;asciinema-render.js?h=50a9efc07f633b5258b8&quot; defer&gt;&lt;&#x2F;script&gt;&lt;h2 id=&quot;what-makes-it-different&quot;&gt;what makes it different&lt;a class=&quot;post-anchor&quot; href=&quot;#what-makes-it-different&quot; aria-label=&quot;Anchor link for: what-makes-it-different&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;Three things, and the sandbox is just one of them.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;It&#x27;s a framework, not a product.&lt;&#x2F;strong&gt; You build agents with it and drop them where you need: a component inside a bigger program, or a sidecar that runs next to a service and acts on what it sees, not a chat box you sit in front of. You extend it by filling the slots it defines, a &lt;code&gt;Tool&lt;&#x2F;code&gt;, an &lt;code&gt;Observer&lt;&#x2F;code&gt;, a provider, a guard, and soon an API and plugins. A run is durable and observable too: it checkpoints as it goes and resumes off disk after a crash, and anything can subscribe to it at once, a terminal UI, an editor, a CI bot. The agent is a process you watch, not a function you call once.&lt;&#x2F;p&gt;
&lt;p&gt;Here&#x27;s the shape of it. The loop in the middle (&lt;code&gt;tk-agent&lt;&#x2F;code&gt;) is the only part you don&#x27;t swap; the crates around it are the slots you fill and the subsystems it leans on:&lt;&#x2F;p&gt;
&lt;pre class=&quot;mermaid&quot;&gt;flowchart TB
    Surfaces[&amp;quot;&amp;lt;b&amp;gt;drive it from&amp;lt;&amp;#x2F;b&amp;gt;&amp;lt;br&amp;#x2F;&amp;gt;tk-cli · tk-acp (sidecar) · tk-cron · tk-plugin · or embed the crate&amp;quot;]
    Loop[&amp;quot;&amp;lt;b&amp;gt;tk-agent, the loop&amp;lt;&amp;#x2F;b&amp;gt;&amp;lt;br&amp;#x2F;&amp;gt;streaming · retries · context compaction · checkpoint &amp;amp;amp; resume · Observers&amp;quot;]
    Gen[&amp;quot;&amp;lt;b&amp;gt;generation&amp;lt;&amp;#x2F;b&amp;gt;&amp;lt;br&amp;#x2F;&amp;gt;tk-providers (wire) · tk-context · tk-prompt · tk-auth · tk-telemetry&amp;quot;]
    Tools[&amp;quot;&amp;lt;b&amp;gt;tools &amp;amp;amp; extension&amp;lt;&amp;#x2F;b&amp;gt;&amp;lt;br&amp;#x2F;&amp;gt;tk-tools · tk-mcp · tk-search (fff) · tk-memory · tk-skills · tk-rubric (guards) · tk-snapshot&amp;quot;]
    Iso[&amp;quot;&amp;lt;b&amp;gt;execution &amp;amp;amp; isolation&amp;lt;&amp;#x2F;b&amp;gt;&amp;lt;br&amp;#x2F;&amp;gt;tk-sandbox · tk-fs (ACL VFS) · tk-subagent · tk-profiles&amp;quot;]
    Dur[&amp;quot;&amp;lt;b&amp;gt;durability &amp;amp;amp; orchestration&amp;lt;&amp;#x2F;b&amp;gt;&amp;lt;br&amp;#x2F;&amp;gt;tk-graph (BSP) · tk-graph-sqlite · tk-workflow&amp;quot;]
    Found[&amp;quot;&amp;lt;b&amp;gt;foundation&amp;lt;&amp;#x2F;b&amp;gt;&amp;lt;br&amp;#x2F;&amp;gt;tk-core · tk-tower&amp;quot;]

    Surfaces --&amp;gt; Loop
    Loop --&amp;gt; Gen
    Loop --&amp;gt; Tools
    Tools --&amp;gt; Iso
    Loop --&amp;gt; Dur
    Loop --&amp;gt; Found&lt;&#x2F;pre&gt;&lt;script src=&quot;https:&#x2F;&#x2F;blog.borai.dev&#x2F;js&#x2F;mermaid-render.js?h=5f96ac3997045c588648&quot; defer&gt;&lt;&#x2F;script&gt;
&lt;p&gt;&lt;strong&gt;It&#x27;s Rust the whole way down.&lt;&#x2F;strong&gt; The only tool that runs a shell is the one literally named &lt;code&gt;shell&lt;&#x2F;code&gt;. grep, search, read, edit, hashing, a jq-style query: all Rust libraries called in-process, no &lt;code&gt;&#x2F;bin&#x2F;sh&lt;&#x2F;code&gt; in the loop. One static binary, and any OpenAI- or Anthropic-wire model is a line of config.&lt;&#x2F;p&gt;
&lt;p&gt;&lt;strong&gt;A tool&#x27;s authority is part of its type.&lt;&#x2F;strong&gt; What a tool can touch is declared on the type itself, a &lt;code&gt;SandboxClass&lt;&#x2F;code&gt; and a &lt;code&gt;const PERMISSIONS&lt;&#x2F;code&gt;, and one gate checks it before the call ever runs, so a read-only agent can&#x27;t be talked into &lt;code&gt;write_file&lt;&#x2F;code&gt; no matter what the model emits. I haven&#x27;t found another agent library that draws that line.&lt;&#x2F;p&gt;
&lt;p&gt;And to be straight: that OS-level sandbox is the youngest part, rlimits plus a best-effort network deny today, not a VM. The type-level gate is real and shipping; the heavier isolation tiers are designed and next.&lt;&#x2F;p&gt;
&lt;h2 id=&quot;where-it-s-going&quot;&gt;where it&#x27;s going&lt;a class=&quot;post-anchor&quot; href=&quot;#where-it-s-going&quot; aria-label=&quot;Anchor link for: where-it-s-going&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;#&lt;&#x2F;span&gt;&lt;&#x2F;a&gt;
&lt;&#x2F;h2&gt;
&lt;p&gt;The shape I&#x27;m building toward is an agent that runs with nobody watching: headless in CI, fixing a flaky test from a &lt;code&gt;&#x2F;takween&lt;&#x2F;code&gt; comment on a pull request; a sidecar beside a live service; and eventually the reason I started, the security work, taking one fixed bug and hunting for the same shape across a codebase. I&#x27;ll write about each as it lands, in more detail than fits here: the type-level sandbox, the tools that never shell out, and how the whole thing runs headless.&lt;&#x2F;p&gt;
&lt;p&gt;takween isn&#x27;t public yet. I&#x27;d rather open it when it&#x27;s ready than when it&#x27;s loud. Follow along here.&lt;&#x2F;p&gt;
</content>
        
    </entry>
</feed>
