Buckets:
| import{s as Wl,n as xl,o as Gl}from"../chunks/scheduler.b8c17244.js";import{S as ql,i as Nl,e as c,s as a,c as M,h as Hl,a as j,d as t,b as n,f as Xl,g as p,j as J,k as _l,l as Fl,m as e,n as y,t as i,o,p as U}from"../chunks/index.d374165a.js";import{C as zl,H as m,E as Yl}from"../chunks/MermaidChart.svelte_svelte_type_style_lang.200f62db.js";import{C as r}from"../chunks/CodeBlock.1a49eeaf.js";function vl(Tl){let T,Ts,ms,ws,w,ds,d,hs,h,wl="Tools are the agent’s hands. Nano Harness enforces its security model at the tool boundary: path confinement, command allowlists, output limits, and write-off-by-default.",us,u,dl='<img src="https://huggingface.co/datasets/mcp-course/images/resolve/main/unit5/tool-sandbox.svg" alt="Layered sandbox security model showing workspace isolation and path validation"/>',Is,I,Cs,C,fs,f,gs,g,hl="<code>safe_path()</code> blocks directory traversal (e.g., <code>../../etc/passwd</code>), the return values are filenames only — not absolute paths — and directories are suffixed with <code>/</code>.",bs,b,ul="<strong>Examples:</strong>",Bs,B,$s,$,As,A,Zs,Z,Il="Paths go through <code>safe_path()</code>, the requested character count is capped at <code>MAX_CHARS</code>, and <code>errors="replace"</code> keeps binary files from crashing the read. Even if the agent asks for <code>max_chars=999999</code>, <code>min(999999, 8000)</code> wins.",ks,k,Cl="<strong>Examples:</strong>",Qs,Q,Vs,V,Es,E,Rs,R,fl="Writing is off by default — the agent must have <code>ALLOW_WRITE=True</code> to touch disk. Paths are confined, and parent directories are created on demand.",Ss,S,gl="<strong>Usage:</strong>",Xs,X,_s,_,Ws,W,xs,x,bl="Only commands in the allowlist run — <code>ls</code>, <code>cat</code>, <code>pwd</code>, <code>echo</code>, <code>head</code>, <code>tail</code>, <code>wc</code>, <code>rg</code>. Anything that mutates state or reaches the network (<code>rm</code>, <code>mv</code>, <code>curl</code>, <code>wget</code>) is rejected. A subprocess timeout stops hangs, and the output is clipped to <code>MAX_CHARS</code>.",Gs,G,Bl="<strong>Examples:</strong>",qs,q,Ns,N,Hs,H,$l="Everything that takes a path flows through this one function:",Fs,F,zs,z,Al="<strong>What it prevents:</strong>",Ys,Y,vs,v,Ls,L,Ks,K,Zl="When executing agent code:",Ds,D,Os,O,Ps,P,kl="Exceptions are caught and reported:",sl,ss,ll,ls,Ql="<strong>Example workflow:</strong>",tl,ts,el,es,al,as,Vl="Commercial agents handle the same concerns behind the scenes. Claude Code and Codex both enforce path confinement, permission prompts, timeouts, and output limits automatically; the cost is that the rules are less visible. Nano Harness keeps everything explicit so you can read and modify the policy, at the cost of having to implement it yourself.",nl,ns,Ml,Ms,El="If you extend nano_harness with new tools, follow these patterns:",pl,ps,yl,ys,il,is,ol,os,Ul,Us,cl,cs,Rl="Limit what tools can reach. <code>safe_path()</code> keeps file access inside the workspace, command allowlists gate subprocess calls, output is clipped to stop context blowups, and writing is off until you turn it on. Errors become observations so the agent can adapt instead of crashing.",jl,js,Sl="Next, extending nano_harness with new tools and models.",Jl,Js,ml,rs,rl;return w=new zl({props:{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"}}),d=new m({props:{title:"Tools and Sandboxing in Detail",local:"tools-and-sandboxing-in-detail",headingTag:"h1"}}),I=new m({props:{title:"The Four Tools",local:"the-four-tools",headingTag:"h2"}}),C=new m({props:{title:"1. list_dir(path) — List Files",local:"1-listdirpath--list-files",headingTag:"h3"}}),f=new r({props:{code:"ZGVmJTIwbGlzdF9kaXIocGF0aCUzRCUyMi4lMjIpJTNBJTBBJTIwJTIwJTIwJTIwJTIyJTIyJTIyTGlzdCUyMGZpbGVzJTIwYW5kJTIwZGlyZWN0b3JpZXMuJTIyJTIyJTIyJTBBJTIwJTIwJTIwJTIwcCUyMCUzRCUyMHNhZmVfcGF0aChwYXRoKSUyMCUyMCUyMyUyMFZlcmlmeSUyMHBhdGglMjBpcyUyMGluJTIwd29ya3NwYWNlJTBBJTIwJTIwJTIwJTIwaWYlMjBub3QlMjBwLmlzX2RpcigpJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmFpc2UlMjBOb3RBRGlyZWN0b3J5RXJyb3Ioc3RyKHApKSUwQSUyMCUyMCUyMCUyMHJldHVybiUyMHNvcnRlZCh4Lm5hbWUlMjAlMkIlMjAoJTIyJTJGJTIyJTIwaWYlMjB4LmlzX2RpcigpJTIwZWxzZSUyMCUyMiUyMiklMjBmb3IlMjB4JTIwaW4lMjBwLml0ZXJkaXIoKSk=",highlighted:`<span class="hljs-keyword">def</span> <span class="hljs-title function_">list_dir</span>(<span class="hljs-params">path=<span class="hljs-string">"."</span></span>): | |
| <span class="hljs-string">"""List files and directories."""</span> | |
| p = safe_path(path) <span class="hljs-comment"># Verify path is in workspace</span> | |
| <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> p.is_dir(): | |
| <span class="hljs-keyword">raise</span> NotADirectoryError(<span class="hljs-built_in">str</span>(p)) | |
| <span class="hljs-keyword">return</span> <span class="hljs-built_in">sorted</span>(x.name + (<span class="hljs-string">"/"</span> <span class="hljs-keyword">if</span> x.is_dir() <span class="hljs-keyword">else</span> <span class="hljs-string">""</span>) <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> p.iterdir())`,wrap:!1}}),B=new r({props:{code:"bGlzdF9kaXIoJTIyLiUyMiklMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjMlMjAlRTIlOUMlOTMlMjBPSyUwQWxpc3RfZGlyKCUyMnNyYyUyMiklMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjMlMjAlRTIlOUMlOTMlMjBPSyUwQWxpc3RfZGlyKCUyMi4uJTJGZXRjJTIyKSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMyUyMCVFMiU5QyU5NyUyMEJMT0NLRUQlMjBieSUyMHNhZmVfcGF0aCgp",highlighted:`list_dir(<span class="hljs-string">"."</span>) <span class="hljs-comment"># ✓ OK</span> | |
| list_dir(<span class="hljs-string">"src"</span>) <span class="hljs-comment"># ✓ OK</span> | |
| list_dir(<span class="hljs-string">"../etc"</span>) <span class="hljs-comment"># ✗ BLOCKED by safe_path()</span>`,wrap:!1}}),$=new m({props:{title:"2. read_file(path, max_chars) — Read File",local:"2-readfilepath-maxchars--read-file",headingTag:"h3"}}),A=new r({props:{code:"ZGVmJTIwcmVhZF9maWxlKHBhdGglMkMlMjBtYXhfY2hhcnMlM0Q0MDAwKSUzQSUwQSUyMCUyMCUyMCUyMCUyMiUyMiUyMlJlYWQlMjBmaWxlJTIwd2l0aCUyMHNpemUlMjBsaW1pdC4lMjIlMjIlMjIlMEElMjAlMjAlMjAlMjBwJTIwJTNEJTIwc2FmZV9wYXRoKHBhdGgpJTBBJTIwJTIwJTIwJTIwY29udGVudCUyMCUzRCUyMHAucmVhZF90ZXh0KGVuY29kaW5nJTNEJTIydXRmLTglMjIlMkMlMjBlcnJvcnMlM0QlMjJyZXBsYWNlJTIyKSUwQSUyMCUyMCUyMCUyMCUyMyUyMEVuZm9yY2UlMjBmcmFtZXdvcmstbGV2ZWwlMjBsaW1pdCUwQSUyMCUyMCUyMCUyMHJldHVybiUyMGNsaXAoY29udGVudCUyQyUyMG1pbihtYXhfY2hhcnMlMkMlMjBNQVhfQ0hBUlMpKSUyMCUyMCUyMyUyME1BWF9DSEFSUyUzRDgwMDA=",highlighted:`<span class="hljs-keyword">def</span> <span class="hljs-title function_">read_file</span>(<span class="hljs-params">path, max_chars=<span class="hljs-number">4000</span></span>): | |
| <span class="hljs-string">"""Read file with size limit."""</span> | |
| p = safe_path(path) | |
| content = p.read_text(encoding=<span class="hljs-string">"utf-8"</span>, errors=<span class="hljs-string">"replace"</span>) | |
| <span class="hljs-comment"># Enforce framework-level limit</span> | |
| <span class="hljs-keyword">return</span> clip(content, <span class="hljs-built_in">min</span>(max_chars, MAX_CHARS)) <span class="hljs-comment"># MAX_CHARS=8000</span>`,wrap:!1}}),Q=new r({props:{code:"cmVhZF9maWxlKCUyMlJFQURNRS5tZCUyMiklMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjMlMjAlRTIlOUMlOTMlMjBVcCUyMHRvJTIwNDAwMCUyMGNoYXJzJTBBcmVhZF9maWxlKCUyMmRhdGEudHh0JTIyJTJDJTIwbWF4X2NoYXJzJTNENTAwKSUyMCUyMCUyMyUyMCVFMiU5QyU5MyUyMFVwJTIwdG8lMjA1MDAlMjBjaGFycyUwQXJlYWRfZmlsZSglMjJodWdlLmRiJTIyKSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMyUyMCVFMiU5QyU5MyUyMENsaXBwZWQlMjB0byUyMDgwMDAlMjBjaGFycyUyMChub3QlMjB1bmxpbWl0ZWQpJTBBcmVhZF9maWxlKCUyMiUyRmV0YyUyRnBhc3N3ZCUyMiklMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjMlMjAlRTIlOUMlOTclMjBCTE9DS0VEJTIwYnklMjBzYWZlX3BhdGgoKQ==",highlighted:`read_file(<span class="hljs-string">"README.md"</span>) <span class="hljs-comment"># ✓ Up to 4000 chars</span> | |
| read_file(<span class="hljs-string">"data.txt"</span>, max_chars=<span class="hljs-number">500</span>) <span class="hljs-comment"># ✓ Up to 500 chars</span> | |
| read_file(<span class="hljs-string">"huge.db"</span>) <span class="hljs-comment"># ✓ Clipped to 8000 chars (not unlimited)</span> | |
| read_file(<span class="hljs-string">"/etc/passwd"</span>) <span class="hljs-comment"># ✗ BLOCKED by safe_path()</span>`,wrap:!1}}),V=new m({props:{title:"3. write_file(path, content) — Write File",local:"3-writefilepath-content--write-file",headingTag:"h3"}}),E=new r({props:{code:"QUxMT1dfV1JJVEUlMjAlM0QlMjBGYWxzZSUyMCUyMCUyMyUyMERpc2FibGVkJTIwYnklMjBkZWZhdWx0ISUwQSUwQWRlZiUyMHdyaXRlX2ZpbGUocGF0aCUyQyUyMGNvbnRlbnQpJTNBJTBBJTIwJTIwJTIwJTIwJTIyJTIyJTIyV3JpdGUlMjBmaWxlJTIwKGdhdGVkJTIwYnklMjBBTExPV19XUklURSUyMGZsYWcpLiUyMiUyMiUyMiUwQSUyMCUyMCUyMCUyMGlmJTIwbm90JTIwQUxMT1dfV1JJVEUlM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByYWlzZSUyMFBlcm1pc3Npb25FcnJvciglMjJ3cml0ZV9maWxlJTIwZGlzYWJsZWQlMjIpJTBBJTIwJTIwJTIwJTIwJTBBJTIwJTIwJTIwJTIwcCUyMCUzRCUyMHNhZmVfcGF0aChwYXRoKSUwQSUyMCUyMCUyMCUyMHAucGFyZW50Lm1rZGlyKHBhcmVudHMlM0RUcnVlJTJDJTIwZXhpc3Rfb2slM0RUcnVlKSUwQSUyMCUyMCUyMCUyMHAud3JpdGVfdGV4dChzdHIoY29udGVudCklMkMlMjBlbmNvZGluZyUzRCUyMnV0Zi04JTIyKSUwQSUyMCUyMCUyMCUyMHJldHVybiUyMGYlMjJXcm90ZSUyMCU3Qmxlbihjb250ZW50KSU3RCUyMGJ5dGVzJTIwdG8lMjAlN0JwJTdEJTIy",highlighted:`ALLOW_WRITE = <span class="hljs-literal">False</span> <span class="hljs-comment"># Disabled by default!</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">write_file</span>(<span class="hljs-params">path, content</span>): | |
| <span class="hljs-string">"""Write file (gated by ALLOW_WRITE flag)."""</span> | |
| <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> ALLOW_WRITE: | |
| <span class="hljs-keyword">raise</span> PermissionError(<span class="hljs-string">"write_file disabled"</span>) | |
| p = safe_path(path) | |
| p.parent.mkdir(parents=<span class="hljs-literal">True</span>, exist_ok=<span class="hljs-literal">True</span>) | |
| p.write_text(<span class="hljs-built_in">str</span>(content), encoding=<span class="hljs-string">"utf-8"</span>) | |
| <span class="hljs-keyword">return</span> <span class="hljs-string">f"Wrote <span class="hljs-subst">{<span class="hljs-built_in">len</span>(content)}</span> bytes to <span class="hljs-subst">{p}</span>"</span>`,wrap:!1}}),X=new r({props:{code:"JTIzJTIwRW5hYmxlJTIwd3JpdGUlMjBleHBsaWNpdGx5JTBBQUxMT1dfV1JJVEUlMjAlM0QlMjBUcnVlJTBBJTBBd3JpdGVfZmlsZSglMjJvdXRwdXQudHh0JTIyJTJDJTIwJTIySGVsbG8lMjIpJTIwJTIwJTIzJTIwJUUyJTlDJTkzJTIwT0slMjBpZiUyMEFMTE9XX1dSSVRFJTNEVHJ1ZQ==",highlighted:`<span class="hljs-comment"># Enable write explicitly</span> | |
| ALLOW_WRITE = <span class="hljs-literal">True</span> | |
| write_file(<span class="hljs-string">"output.txt"</span>, <span class="hljs-string">"Hello"</span>) <span class="hljs-comment"># ✓ OK if ALLOW_WRITE=True</span>`,wrap:!1}}),_=new m({props:{title:"4. exec_cmd(args) — Execute Shell Command",local:"4-execcmdargs--execute-shell-command",headingTag:"h3"}}),W=new r({props:{code:"QUxMT1dfQ09NTUFORFMlMjAlM0QlMjAlNUIlMjJscyUyMiUyQyUyMCUyMmNhdCUyMiUyQyUyMCUyMnB3ZCUyMiUyQyUyMCUyMmVjaG8lMjIlMkMlMjAlMjJoZWFkJTIyJTJDJTIwJTIydGFpbCUyMiUyQyUyMCUyMndjJTIyJTJDJTIwJTIycmclMjIlNUQlMEElMEFkZWYlMjBleGVjX2NtZChhcmdzKSUzQSUwQSUyMCUyMCUyMCUyMCUyMiUyMiUyMkV4ZWN1dGUlMjBjb21tYW5kJTIwKHdoaXRlbGlzdCUyMG9ubHkpLiUyMiUyMiUyMiUwQSUyMCUyMCUyMCUyMGlmJTIwYXJncyU1QjAlNUQlMjBub3QlMjBpbiUyMEFMTE9XX0NPTU1BTkRTJTNBJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwcmFpc2UlMjBQZXJtaXNzaW9uRXJyb3IoZiUyMkNvbW1hbmQlMjAnJTdCYXJncyU1QjAlNUQlN0QnJTIwbm90JTIwYWxsb3dlZCUyMiklMEElMjAlMjAlMjAlMjAlMEElMjAlMjAlMjAlMjB0cnklM0ElMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXN1bHQlMjAlM0QlMjBzdWJwcm9jZXNzLnJ1biglMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjBhcmdzJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwY2FwdHVyZV9vdXRwdXQlM0RUcnVlJTJDJTBBJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwdGltZW91dCUzRFRJTUVPVVRfUyUyQyUyMCUyMCUyMyUyMGUuZy4lMkMlMjAzMCUyMHNlY29uZHMlMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjB0ZXh0JTNEVHJ1ZSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMCklMEElMjAlMjAlMjAlMjAlMjAlMjAlMjAlMjByZXR1cm4lMjBjbGlwKHJlc3VsdC5zdGRvdXQlMkMlMjBNQVhfQ0hBUlMpJTBBJTIwJTIwJTIwJTIwZXhjZXB0JTIwc3VicHJvY2Vzcy5UaW1lb3V0RXhwaXJlZCUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJldHVybiUyMCUyMkVycm9yJTNBJTIwQ29tbWFuZCUyMHRpbWVkJTIwb3V0JTIy",highlighted:`ALLOW_COMMANDS = [<span class="hljs-string">"ls"</span>, <span class="hljs-string">"cat"</span>, <span class="hljs-string">"pwd"</span>, <span class="hljs-string">"echo"</span>, <span class="hljs-string">"head"</span>, <span class="hljs-string">"tail"</span>, <span class="hljs-string">"wc"</span>, <span class="hljs-string">"rg"</span>] | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">exec_cmd</span>(<span class="hljs-params">args</span>): | |
| <span class="hljs-string">"""Execute command (whitelist only)."""</span> | |
| <span class="hljs-keyword">if</span> args[<span class="hljs-number">0</span>] <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> ALLOW_COMMANDS: | |
| <span class="hljs-keyword">raise</span> PermissionError(<span class="hljs-string">f"Command '<span class="hljs-subst">{args[<span class="hljs-number">0</span>]}</span>' not allowed"</span>) | |
| <span class="hljs-keyword">try</span>: | |
| result = subprocess.run( | |
| args, | |
| capture_output=<span class="hljs-literal">True</span>, | |
| timeout=TIMEOUT_S, <span class="hljs-comment"># e.g., 30 seconds</span> | |
| text=<span class="hljs-literal">True</span> | |
| ) | |
| <span class="hljs-keyword">return</span> clip(result.stdout, MAX_CHARS) | |
| <span class="hljs-keyword">except</span> subprocess.TimeoutExpired: | |
| <span class="hljs-keyword">return</span> <span class="hljs-string">"Error: Command timed out"</span>`,wrap:!1}}),q=new r({props:{code:"ZXhlY19jbWQoJTVCJTIybHMlMjIlMkMlMjAlMjItbGElMjIlNUQpJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwJUUyJTlDJTkzJTIwT0slMjAobHMlMjB3aGl0ZWxpc3RlZCklMEFleGVjX2NtZCglNUIlMjJwd2QlMjIlNUQpJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIwJTIzJTIwJUUyJTlDJTkzJTIwT0slMEFleGVjX2NtZCglNUIlMjJyZyUyMiUyQyUyMCUyMkVSUk9SJTIyJTVEKSUyMCUyMCUyMCUyMCUyMyUyMCVFMiU5QyU5MyUyME9LJTIwKHJnJTIwaXMlMjByaXBncmVwJTJDJTIwc2FmZSklMEFleGVjX2NtZCglNUIlMjJybSUyMiUyQyUyMCUyMi1yZiUyMiUyQyUyMCUyMiUyRiUyMiU1RCklMjAlMjMlMjAlRTIlOUMlOTclMjBCTE9DS0VEJTIwKHJtJTIwbm90JTIwd2hpdGVsaXN0ZWQpJTBBZXhlY19jbWQoJTVCJTIyY3VybCUyMiUyQyUyMCUyMmV2aWwuY29tJTIyJTVEKSUyMCUyMCUyMyUyMCVFMiU5QyU5NyUyMEJMT0NLRUQlMjAoY3VybCUyMG5vdCUyMHdoaXRlbGlzdGVkKQ==",highlighted:`exec_cmd([<span class="hljs-string">"ls"</span>, <span class="hljs-string">"-la"</span>]) <span class="hljs-comment"># ✓ OK (ls whitelisted)</span> | |
| exec_cmd([<span class="hljs-string">"pwd"</span>]) <span class="hljs-comment"># ✓ OK</span> | |
| exec_cmd([<span class="hljs-string">"rg"</span>, <span class="hljs-string">"ERROR"</span>]) <span class="hljs-comment"># ✓ OK (rg is ripgrep, safe)</span> | |
| exec_cmd([<span class="hljs-string">"rm"</span>, <span class="hljs-string">"-rf"</span>, <span class="hljs-string">"/"</span>]) <span class="hljs-comment"># ✗ BLOCKED (rm not whitelisted)</span> | |
| exec_cmd([<span class="hljs-string">"curl"</span>, <span class="hljs-string">"evil.com"</span>]) <span class="hljs-comment"># ✗ BLOCKED (curl not whitelisted)</span>`,wrap:!1}}),N=new m({props:{title:"Path Confinement: safe_path()",local:"path-confinement-safepath",headingTag:"h2"}}),F=new r({props:{code:"V09SS1NQQUNFJTIwJTNEJTIwUGF0aC5jd2QoKSUyMCUyMCUyMyUyMGUuZy4lMkMlMjAlMkZob21lJTJGdXNlciUyRnByb2plY3QlMEElMEFkZWYlMjBzYWZlX3BhdGgodXNlcl9pbnB1dCklM0ElMEElMjAlMjAlMjAlMjAlMjIlMjIlMjJFbnN1cmUlMjBwYXRoJTIwaXMlMjB3aXRoaW4lMjB3b3Jrc3BhY2UuJTIyJTIyJTIyJTBBJTIwJTIwJTIwJTIwJTIzJTIwUmVzb2x2ZSUyMHRvJTIwYWJzb2x1dGUlMjBwYXRoJTBBJTIwJTIwJTIwJTIwcmVxdWVzdGVkJTIwJTNEJTIwKFdPUktTUEFDRSUyMCUyRiUyMHVzZXJfaW5wdXQpLnJlc29sdmUoKSUwQSUyMCUyMCUyMCUyMCUwQSUyMCUyMCUyMCUyMCUyMyUyMENoZWNrJTIwaWYlMjBpdCdzJTIwaW5zaWRlJTIwd29ya3NwYWNlJTBBJTIwJTIwJTIwJTIwaWYlMjBub3QlMjByZXF1ZXN0ZWQuaXNfcmVsYXRpdmVfdG8oV09SS1NQQUNFKSUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJhaXNlJTIwVmFsdWVFcnJvcihmJTIyUGF0aCUyMCU3QnVzZXJfaW5wdXQlN0QlMjBlc2NhcGVzJTIwd29ya3NwYWNlJTIyKSUwQSUyMCUyMCUyMCUyMCUwQSUyMCUyMCUyMCUyMHJldHVybiUyMHJlcXVlc3RlZA==",highlighted:`WORKSPACE = Path.cwd() <span class="hljs-comment"># e.g., /home/user/project</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">safe_path</span>(<span class="hljs-params">user_input</span>): | |
| <span class="hljs-string">"""Ensure path is within workspace."""</span> | |
| <span class="hljs-comment"># Resolve to absolute path</span> | |
| requested = (WORKSPACE / user_input).resolve() | |
| <span class="hljs-comment"># Check if it's inside workspace</span> | |
| <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> requested.is_relative_to(WORKSPACE): | |
| <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">f"Path <span class="hljs-subst">{user_input}</span> escapes workspace"</span>) | |
| <span class="hljs-keyword">return</span> requested`,wrap:!1}}),Y=new r({props:{code:"JTIzJTIwQXR0YWNrZXIlMjB0cmllcyUyMGRpcmVjdG9yeSUyMHRyYXZlcnNhbCUwQXNhZmVfcGF0aCglMjIuLiUyRi4uJTJGLi4lMkZldGMlMkZwYXNzd2QlMjIpJTBBJTIzJTIwJUUyJTg2JTkyJTIwUmVzb2x2ZXMlMjB0byUyMCUyRmhvbWUlMkZ1c2VyJTJGcHJvamVjdCUyRi4uJTJGLi4lMkZldGMlMkZwYXNzd2QlMEElMjMlMjAlRTIlODYlOTIlMjBSZXNvbHZlcyUyMHRvJTIwJTJGZXRjJTJGcGFzc3dkJTBBJTIzJTIwJUUyJTg2JTkyJTIwTk9UJTIwcmVsYXRpdmUlMjB0byUyMFdPUktTUEFDRSUwQSUyMyUyMCVFMiU4NiU5MiUyMFJhaXNlcyUyMFZhbHVlRXJyb3IlMjAlRTIlOUMlOTMlMEElMEElMjMlMjBBdHRhY2tlciUyMHRyaWVzJTIwYWJzb2x1dGUlMjBwYXRoJTBBc2FmZV9wYXRoKCUyMiUyRmV0YyUyRnBhc3N3ZCUyMiklMEElMjMlMjAlRTIlODYlOTIlMjBEb2Vzbid0JTIwc3RhcnQlMjB3aXRoJTIwV09SS1NQQUNFJTBBJTIzJTIwJUUyJTg2JTkyJTIwUmFpc2VzJTIwVmFsdWVFcnJvciUyMCVFMiU5QyU5MyUwQSUwQSUyMyUyMExlZ2l0aW1hdGUlMjB1c2UlMEFzYWZlX3BhdGgoJTIyZGF0YSUyRm1vZGVscy50eHQlMjIpJTBBJTIzJTIwJUUyJTg2JTkyJTIwUmVzb2x2ZXMlMjB0byUyMCUyRmhvbWUlMkZ1c2VyJTJGcHJvamVjdCUyRmRhdGElMkZtb2RlbHMudHh0JTBBJTIzJTIwJUUyJTg2JTkyJTIwSVMlMjByZWxhdGl2ZSUyMHRvJTIwV09SS1NQQUNFJTBBJTIzJTIwJUUyJTg2JTkyJTIwUmV0dXJucyUyMHBhdGglMjAlRTIlOUMlOTM=",highlighted:`<span class="hljs-comment"># Attacker tries directory traversal</span> | |
| safe_path(<span class="hljs-string">"../../../etc/passwd"</span>) | |
| <span class="hljs-comment"># → Resolves to /home/user/project/../../etc/passwd</span> | |
| <span class="hljs-comment"># → Resolves to /etc/passwd</span> | |
| <span class="hljs-comment"># → NOT relative to WORKSPACE</span> | |
| <span class="hljs-comment"># → Raises ValueError ✓</span> | |
| <span class="hljs-comment"># Attacker tries absolute path</span> | |
| safe_path(<span class="hljs-string">"/etc/passwd"</span>) | |
| <span class="hljs-comment"># → Doesn't start with WORKSPACE</span> | |
| <span class="hljs-comment"># → Raises ValueError ✓</span> | |
| <span class="hljs-comment"># Legitimate use</span> | |
| safe_path(<span class="hljs-string">"data/models.txt"</span>) | |
| <span class="hljs-comment"># → Resolves to /home/user/project/data/models.txt</span> | |
| <span class="hljs-comment"># → IS relative to WORKSPACE</span> | |
| <span class="hljs-comment"># → Returns path ✓</span>`,wrap:!1}}),v=new m({props:{title:"Execution Sandboxing",local:"execution-sandboxing",headingTag:"h2"}}),L=new m({props:{title:"Limited Global Scope",local:"limited-global-scope",headingTag:"h3"}}),D=new r({props:{code:"JTIzJTIwT25seSUyMHRoZXNlJTIwZnVuY3Rpb25zJTIwYXJlJTIwYXZhaWxhYmxlJTBBZXhlY19nbG9iYWxzJTIwJTNEJTIwJTdCJTBBJTIwJTIwJTIwJTIwJTIybGlzdF9kaXIlMjIlM0ElMjBsaXN0X2RpciUyQyUwQSUyMCUyMCUyMCUyMCUyMnJlYWRfZmlsZSUyMiUzQSUyMHJlYWRfZmlsZSUyQyUwQSUyMCUyMCUyMCUyMCUyMndyaXRlX2ZpbGUlMjIlM0ElMjB3cml0ZV9maWxlJTJDJTBBJTIwJTIwJTIwJTIwJTIyZXhlY19jbWQlMjIlM0ElMjBleGVjX2NtZCUyQyUwQSUyMCUyMCUyMCUyMCUyMmZpbmFsX2Fuc3dlciUyMiUzQSUyMGZpbmFsX2Fuc3dlciUwQSU3RCUwQSUwQSUyMyUyMEFnZW50JTIwY29kZSUyMHJ1bnMlMjBoZXJlJTBBZXhlYyhhZ2VudF9jb2RlJTJDJTIwZXhlY19nbG9iYWxzKSUwQSUwQSUyMyUyMEFnZW50JTIwQ0FOTk9UJTIwZG8lM0ElMEElMjMlMjAtJTIwaW1wb3J0JTIwbW9kdWxlcyUyMChubyUyMF9fYnVpbHRpbnNfXyklMEElMjMlMjAtJTIwYWNjZXNzJTIwZmlsZXMlMjBvdXRzaWRlJTIwdG9vbHMlMEElMjMlMjAtJTIwdXNlJTIwbmV0d29yayUyMGRpcmVjdGx5JTBBJTIzJTIwLSUyMGFjY2VzcyUyMHBhcmVudCUyMHByb2Nlc3MlMjB2YXJpYWJsZXM=",highlighted:`<span class="hljs-comment"># Only these functions are available</span> | |
| exec_globals = { | |
| <span class="hljs-string">"list_dir"</span>: list_dir, | |
| <span class="hljs-string">"read_file"</span>: read_file, | |
| <span class="hljs-string">"write_file"</span>: write_file, | |
| <span class="hljs-string">"exec_cmd"</span>: exec_cmd, | |
| <span class="hljs-string">"final_answer"</span>: final_answer | |
| } | |
| <span class="hljs-comment"># Agent code runs here</span> | |
| <span class="hljs-built_in">exec</span>(agent_code, exec_globals) | |
| <span class="hljs-comment"># Agent CANNOT do:</span> | |
| <span class="hljs-comment"># - import modules (no __builtins__)</span> | |
| <span class="hljs-comment"># - access files outside tools</span> | |
| <span class="hljs-comment"># - use network directly</span> | |
| <span class="hljs-comment"># - access parent process variables</span>`,wrap:!1}}),O=new m({props:{title:"Error Containment",local:"error-containment",headingTag:"h3"}}),ss=new r({props:{code:"dHJ5JTNBJTBBJTIwJTIwJTIwJTIwZXhlYyhhZ2VudF9jb2RlJTJDJTIwZXhlY19nbG9iYWxzKSUwQWV4Y2VwdCUyMEV4Y2VwdGlvbiUyMGFzJTIwZSUzQSUwQSUyMCUyMCUyMCUyMGVycm9yX21zZyUyMCUzRCUyMGYlMjJFcnJvciUzQSUyMCU3QnR5cGUoZSkuX19uYW1lX18lN0QlM0ElMjAlN0JzdHIoZSklN0QlMjIlMEElMjAlMjAlMjAlMjBtZXNzYWdlcy5hcHBlbmQoJTdCJTIycm9sZSUyMiUzQSUyMCUyMnVzZXIlMjIlMkMlMjAlMjJjb250ZW50JTIyJTNBJTIwZXJyb3JfbXNnJTdEKSUwQSUyMCUyMCUyMCUyMCUyMyUyMENvbnRpbnVlJTIwdG8lMjBuZXh0JTIwaXRlcmF0aW9uJTNCJTIwYWdlbnQlMjBhZGFwdHM=",highlighted:`<span class="hljs-keyword">try</span>: | |
| <span class="hljs-built_in">exec</span>(agent_code, exec_globals) | |
| <span class="hljs-keyword">except</span> Exception <span class="hljs-keyword">as</span> e: | |
| error_msg = <span class="hljs-string">f"Error: <span class="hljs-subst">{<span class="hljs-built_in">type</span>(e).__name__}</span>: <span class="hljs-subst">{<span class="hljs-built_in">str</span>(e)}</span>"</span> | |
| messages.append({<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: error_msg}) | |
| <span class="hljs-comment"># Continue to next iteration; agent adapts</span>`,wrap:!1}}),ts=new r({props:{code:"U3RlcCUyMDElM0ElMjBBZ2VudCUyMHRyaWVzJTIwdG8lMjByZWFkJTIwaHVnZSUyMGZpbGUlMEElMjAlMjBDb2RlJTNBJTIwY29udGVudCUyMCUzRCUyMHJlYWRfZmlsZSglMjJodWdlLmRhdCUyMiUyQyUyMG1heF9jaGFycyUzRDk5OTk5OSklMEElMjAlMjBSZXN1bHQlM0ElMjAoQ2xpcHBlZCUyMHRvJTIwODAwMCUyMGNoYXJzJTJDJTIwYWdlbnQlMjBzZWVzJTIwaXQpJTBBJTBBU3RlcCUyMDIlM0ElMjBBZ2VudCUyMHRyaWVzJTIwZm9yYmlkZGVuJTIwY29tbWFuZCUwQSUyMCUyMENvZGUlM0ElMjBleGVjX2NtZCglNUIlMjJybSUyMiUyQyUyMCUyMmRhdGEudHh0JTIyJTVEKSUwQSUyMCUyMFJlc3VsdCUzQSUyMFBlcm1pc3Npb25FcnJvciUzQSUyMENvbW1hbmQlMjAncm0nJTIwbm90JTIwYWxsb3dlZCUwQSUyMCUyMEFnZW50JTIwc2VlcyUyMGVycm9yJTIwYW5kJTIwdHJpZXMlMjBkaWZmZXJlbnQlMjBhcHByb2FjaCUwQSUwQVN0ZXAlMjAzJTNBJTIwQWdlbnQlMjB0cmllcyUyMHRvJTIwZXNjYXBlJTIwd29ya3NwYWNlJTBBJTIwJTIwQ29kZSUzQSUyMHJlYWRfZmlsZSglMjIuLiUyRi4uJTJGLi4lMkZldGMlMkZwYXNzd2QlMjIpJTBBJTIwJTIwUmVzdWx0JTNBJTIwVmFsdWVFcnJvciUzQSUyMFBhdGglMjBlc2NhcGVzJTIwd29ya3NwYWNlJTBBJTIwJTIwQWdlbnQlMjBsZWFybnMlMjBhbmQlMjBhZGp1c3Rz",highlighted:`<span class="hljs-keyword">Step</span> <span class="hljs-number">1</span>: <span class="hljs-built_in">Agent</span> tries <span class="hljs-keyword">to</span> read huge file | |
| Code: content = read_file(<span class="hljs-string">"huge.dat"</span>, max_chars=<span class="hljs-number">999999</span>) | |
| Result: (Clipped <span class="hljs-keyword">to</span> <span class="hljs-number">8000</span> chars, <span class="hljs-built_in">agent</span> sees it) | |
| <span class="hljs-keyword">Step</span> <span class="hljs-number">2</span>: <span class="hljs-built_in">Agent</span> tries forbidden command | |
| Code: exec_cmd([<span class="hljs-string">"rm"</span>, <span class="hljs-string">"data.txt"</span>]) | |
| Result: PermissionError: Command <span class="hljs-string">'rm'</span> <span class="hljs-built_in">not</span> allowed | |
| <span class="hljs-built_in">Agent</span> sees error <span class="hljs-built_in">and</span> tries different approach | |
| <span class="hljs-keyword">Step</span> <span class="hljs-number">3</span>: <span class="hljs-built_in">Agent</span> tries <span class="hljs-keyword">to</span> escape workspace | |
| Code: read_file(<span class="hljs-string">"../../../etc/passwd"</span>) | |
| Result: ValueError: Path escapes workspace | |
| <span class="hljs-built_in">Agent</span> learns <span class="hljs-built_in">and</span> adjusts`,wrap:!1}}),es=new m({props:{title:"Commercial Agents vs. Nano Harness",local:"commercial-agents-vs-nano-harness",headingTag:"h2"}}),ns=new m({props:{title:"Designing Custom Tools",local:"designing-custom-tools",headingTag:"h2"}}),ps=new m({props:{title:"Good Tool Design",local:"good-tool-design",headingTag:"h3"}}),ys=new r({props:{code:"ZGVmJTIwZ29vZF90b29sKHVzZXJfaW5wdXQlMkMlMjBtYXhfcmVzdWx0X3NpemUlM0QxMDAwKSUzQSUwQSUyMCUyMCUyMCUyMCUyMiUyMiUyMiUwQSUyMCUyMCUyMCUyMDEuJTIwVmFsaWRhdGUlMjBhbmQlMjBjb25maW5lJTIwaW5wdXQlMEElMjAlMjAlMjAlMjAyLiUyMFBlcmZvcm0lMjBvcGVyYXRpb24lMEElMjAlMjAlMjAlMjAzLiUyMExpbWl0JTIwb3V0cHV0JTIwc2l6ZSUwQSUyMCUyMCUyMCUyMDQuJTIwUmV0dXJuJTIwc2FmZSUyMHJlc3VsdCUwQSUyMCUyMCUyMCUyMCUyMiUyMiUyMiUwQSUyMCUyMCUyMCUyMCUyMyUyMDEuJTIwVmFsaWRhdGUlMjBpbnB1dCUwQSUyMCUyMCUyMCUyMGlmJTIwbm90JTIwaXNpbnN0YW5jZSh1c2VyX2lucHV0JTJDJTIwc3RyKSUzQSUwQSUyMCUyMCUyMCUyMCUyMCUyMCUyMCUyMHJhaXNlJTIwVHlwZUVycm9yKCUyMnVzZXJfaW5wdXQlMjBtdXN0JTIwYmUlMjBzdHJpbmclMjIpJTBBJTIwJTIwJTIwJTIwJTBBJTIwJTIwJTIwJTIwcGF0aCUyMCUzRCUyMHNhZmVfcGF0aCh1c2VyX2lucHV0KSUyMCUyMCUyMyUyMENvbmZpbmUlMjBwYXRocyUwQSUyMCUyMCUyMCUyMCUwQSUyMCUyMCUyMCUyMCUyMyUyMDIuJTIwUGVyZm9ybSUyMG9wZXJhdGlvbiUwQSUyMCUyMCUyMCUyMHJlc3VsdCUyMCUzRCUyMHBhdGgucmVhZF90ZXh0KCklMEElMjAlMjAlMjAlMjAlMEElMjAlMjAlMjAlMjAlMjMlMjAzLiUyMExpbWl0JTIwb3V0cHV0JTBBJTIwJTIwJTIwJTIwcmV0dXJuJTIwY2xpcChyZXN1bHQlMkMlMjBtaW4obWF4X3Jlc3VsdF9zaXplJTJDJTIwTUFYX0NIQVJTKSk=",highlighted:`<span class="hljs-keyword">def</span> <span class="hljs-title function_">good_tool</span>(<span class="hljs-params">user_input, max_result_size=<span class="hljs-number">1000</span></span>): | |
| <span class="hljs-string">""" | |
| 1. Validate and confine input | |
| 2. Perform operation | |
| 3. Limit output size | |
| 4. Return safe result | |
| """</span> | |
| <span class="hljs-comment"># 1. Validate input</span> | |
| <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> <span class="hljs-built_in">isinstance</span>(user_input, <span class="hljs-built_in">str</span>): | |
| <span class="hljs-keyword">raise</span> TypeError(<span class="hljs-string">"user_input must be string"</span>) | |
| path = safe_path(user_input) <span class="hljs-comment"># Confine paths</span> | |
| <span class="hljs-comment"># 2. Perform operation</span> | |
| result = path.read_text() | |
| <span class="hljs-comment"># 3. Limit output</span> | |
| <span class="hljs-keyword">return</span> clip(result, <span class="hljs-built_in">min</span>(max_result_size, MAX_CHARS))`,wrap:!1}}),is=new m({props:{title:"Tool Anti-Patterns",local:"tool-anti-patterns",headingTag:"h3"}}),os=new r({props:{code:"JTIzJTIwJUUyJTlDJTk3JTIwQkFEJTNBJTIwTm8lMjBpbnB1dCUyMHZhbGlkYXRpb24lMEFkZWYlMjBiYWRfdG9vbF8xKHBhdGgpJTNBJTBBJTIwJTIwJTIwJTIwcmV0dXJuJTIwb3BlbihwYXRoKS5yZWFkKCklMjAlMjAlMjMlMjBSZWFkcyUyMGFueXRoaW5nISUwQSUwQSUyMyUyMCVFMiU5QyU5NyUyMEJBRCUzQSUyME5vJTIwb3V0cHV0JTIwbGltaXQlMEFkZWYlMjBiYWRfdG9vbF8yKHF1ZXJ5KSUzQSUwQSUyMCUyMCUyMCUyMHJldHVybiUyMGRhdGFiYXNlLnF1ZXJ5KHF1ZXJ5KSUyMCUyMCUyMyUyMENvdWxkJTIwYmUlMjB0ZXJhYnl0ZXMlMEElMEElMjMlMjAlRTIlOUMlOTclMjBCQUQlM0ElMjBObyUyMGVycm9yJTIwaGFuZGxpbmclMEFkZWYlMjBiYWRfdG9vbF8zKHVybCklM0ElMEElMjAlMjAlMjAlMjByZXR1cm4lMjByZXF1ZXN0cy5nZXQodXJsKS50ZXh0JTIwJTIwJTIzJTIwQ2FuJTIwdGltZW91dCUyQyUyMGhhbmclMEElMEElMjMlMjAlRTIlOUMlOTclMjBCQUQlM0ElMjBUcnVzdHMlMjBhZ2VudCUyMGNvbXBsZXRlbHklMEFkZWYlMjBiYWRfdG9vbF80KGNvbW1hbmQpJTNBJTBBJTIwJTIwJTIwJTIwb3Muc3lzdGVtKGNvbW1hbmQpJTIwJTIwJTIzJTIwQWdlbnQlMjBjYW4lMjBydW4lMjBybSUyMC1yZiUyMCUyRg==",highlighted:`<span class="hljs-comment"># ✗ BAD: No input validation</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">bad_tool_1</span>(<span class="hljs-params">path</span>): | |
| <span class="hljs-keyword">return</span> <span class="hljs-built_in">open</span>(path).read() <span class="hljs-comment"># Reads anything!</span> | |
| <span class="hljs-comment"># ✗ BAD: No output limit</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">bad_tool_2</span>(<span class="hljs-params">query</span>): | |
| <span class="hljs-keyword">return</span> database.query(query) <span class="hljs-comment"># Could be terabytes</span> | |
| <span class="hljs-comment"># ✗ BAD: No error handling</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">bad_tool_3</span>(<span class="hljs-params">url</span>): | |
| <span class="hljs-keyword">return</span> requests.get(url).text <span class="hljs-comment"># Can timeout, hang</span> | |
| <span class="hljs-comment"># ✗ BAD: Trusts agent completely</span> | |
| <span class="hljs-keyword">def</span> <span class="hljs-title function_">bad_tool_4</span>(<span class="hljs-params">command</span>): | |
| os.system(command) <span class="hljs-comment"># Agent can run rm -rf /</span>`,wrap:!1}}),Us=new m({props:{title:"Key Takeaways",local:"key-takeaways",headingTag:"h2"}}),Js=new Yl({props:{source:"https://github.com/huggingface/context-course/blob/main/units/en/unit5/tools-and-sandboxing.mdx"}}),{c(){T=c("meta"),Ts=a(),ms=c("p"),ws=a(),M(w.$$.fragment),ds=a(),M(d.$$.fragment),hs=a(),h=c("p"),h.textContent=wl,us=a(),u=c("p"),u.innerHTML=dl,Is=a(),M(I.$$.fragment),Cs=a(),M(C.$$.fragment),fs=a(),M(f.$$.fragment),gs=a(),g=c("p"),g.innerHTML=hl,bs=a(),b=c("p"),b.innerHTML=ul,Bs=a(),M(B.$$.fragment),$s=a(),M($.$$.fragment),As=a(),M(A.$$.fragment),Zs=a(),Z=c("p"),Z.innerHTML=Il,ks=a(),k=c("p"),k.innerHTML=Cl,Qs=a(),M(Q.$$.fragment),Vs=a(),M(V.$$.fragment),Es=a(),M(E.$$.fragment),Rs=a(),R=c("p"),R.innerHTML=fl,Ss=a(),S=c("p"),S.innerHTML=gl,Xs=a(),M(X.$$.fragment),_s=a(),M(_.$$.fragment),Ws=a(),M(W.$$.fragment),xs=a(),x=c("p"),x.innerHTML=bl,Gs=a(),G=c("p"),G.innerHTML=Bl,qs=a(),M(q.$$.fragment),Ns=a(),M(N.$$.fragment),Hs=a(),H=c("p"),H.textContent=$l,Fs=a(),M(F.$$.fragment),zs=a(),z=c("p"),z.innerHTML=Al,Ys=a(),M(Y.$$.fragment),vs=a(),M(v.$$.fragment),Ls=a(),M(L.$$.fragment),Ks=a(),K=c("p"),K.textContent=Zl,Ds=a(),M(D.$$.fragment),Os=a(),M(O.$$.fragment),Ps=a(),P=c("p"),P.textContent=kl,sl=a(),M(ss.$$.fragment),ll=a(),ls=c("p"),ls.innerHTML=Ql,tl=a(),M(ts.$$.fragment),el=a(),M(es.$$.fragment),al=a(),as=c("p"),as.textContent=Vl,nl=a(),M(ns.$$.fragment),Ml=a(),Ms=c("p"),Ms.textContent=El,pl=a(),M(ps.$$.fragment),yl=a(),M(ys.$$.fragment),il=a(),M(is.$$.fragment),ol=a(),M(os.$$.fragment),Ul=a(),M(Us.$$.fragment),cl=a(),cs=c("p"),cs.innerHTML=Rl,jl=a(),js=c("p"),js.textContent=Sl,Jl=a(),M(Js.$$.fragment),ml=a(),rs=c("p"),this.h()},l(s){const l=Hl("svelte-u9bgzb",document.head);T=j(l,"META",{name:!0,content:!0}),l.forEach(t),Ts=n(s),ms=j(s,"P",{}),Xl(ms).forEach(t),ws=n(s),p(w.$$.fragment,s),ds=n(s),p(d.$$.fragment,s),hs=n(s),h=j(s,"P",{"data-svelte-h":!0}),J(h)!=="svelte-1r3fkkq"&&(h.textContent=wl),us=n(s),u=j(s,"P",{"data-svelte-h":!0}),J(u)!=="svelte-14vyn72"&&(u.innerHTML=dl),Is=n(s),p(I.$$.fragment,s),Cs=n(s),p(C.$$.fragment,s),fs=n(s),p(f.$$.fragment,s),gs=n(s),g=j(s,"P",{"data-svelte-h":!0}),J(g)!=="svelte-1m59cjm"&&(g.innerHTML=hl),bs=n(s),b=j(s,"P",{"data-svelte-h":!0}),J(b)!=="svelte-1r5zqy"&&(b.innerHTML=ul),Bs=n(s),p(B.$$.fragment,s),$s=n(s),p($.$$.fragment,s),As=n(s),p(A.$$.fragment,s),Zs=n(s),Z=j(s,"P",{"data-svelte-h":!0}),J(Z)!=="svelte-1s8tlff"&&(Z.innerHTML=Il),ks=n(s),k=j(s,"P",{"data-svelte-h":!0}),J(k)!=="svelte-1r5zqy"&&(k.innerHTML=Cl),Qs=n(s),p(Q.$$.fragment,s),Vs=n(s),p(V.$$.fragment,s),Es=n(s),p(E.$$.fragment,s),Rs=n(s),R=j(s,"P",{"data-svelte-h":!0}),J(R)!=="svelte-18jf5uq"&&(R.innerHTML=fl),Ss=n(s),S=j(s,"P",{"data-svelte-h":!0}),J(S)!=="svelte-qbjyqk"&&(S.innerHTML=gl),Xs=n(s),p(X.$$.fragment,s),_s=n(s),p(_.$$.fragment,s),Ws=n(s),p(W.$$.fragment,s),xs=n(s),x=j(s,"P",{"data-svelte-h":!0}),J(x)!=="svelte-1pypcvf"&&(x.innerHTML=bl),Gs=n(s),G=j(s,"P",{"data-svelte-h":!0}),J(G)!=="svelte-1r5zqy"&&(G.innerHTML=Bl),qs=n(s),p(q.$$.fragment,s),Ns=n(s),p(N.$$.fragment,s),Hs=n(s),H=j(s,"P",{"data-svelte-h":!0}),J(H)!=="svelte-2g5qca"&&(H.textContent=$l),Fs=n(s),p(F.$$.fragment,s),zs=n(s),z=j(s,"P",{"data-svelte-h":!0}),J(z)!=="svelte-1gobu5"&&(z.innerHTML=Al),Ys=n(s),p(Y.$$.fragment,s),vs=n(s),p(v.$$.fragment,s),Ls=n(s),p(L.$$.fragment,s),Ks=n(s),K=j(s,"P",{"data-svelte-h":!0}),J(K)!=="svelte-plczgc"&&(K.textContent=Zl),Ds=n(s),p(D.$$.fragment,s),Os=n(s),p(O.$$.fragment,s),Ps=n(s),P=j(s,"P",{"data-svelte-h":!0}),J(P)!=="svelte-jxlh52"&&(P.textContent=kl),sl=n(s),p(ss.$$.fragment,s),ll=n(s),ls=j(s,"P",{"data-svelte-h":!0}),J(ls)!=="svelte-13a3le6"&&(ls.innerHTML=Ql),tl=n(s),p(ts.$$.fragment,s),el=n(s),p(es.$$.fragment,s),al=n(s),as=j(s,"P",{"data-svelte-h":!0}),J(as)!=="svelte-rmhxpw"&&(as.textContent=Vl),nl=n(s),p(ns.$$.fragment,s),Ml=n(s),Ms=j(s,"P",{"data-svelte-h":!0}),J(Ms)!=="svelte-1hmwjf7"&&(Ms.textContent=El),pl=n(s),p(ps.$$.fragment,s),yl=n(s),p(ys.$$.fragment,s),il=n(s),p(is.$$.fragment,s),ol=n(s),p(os.$$.fragment,s),Ul=n(s),p(Us.$$.fragment,s),cl=n(s),cs=j(s,"P",{"data-svelte-h":!0}),J(cs)!=="svelte-oxg4q9"&&(cs.innerHTML=Rl),jl=n(s),js=j(s,"P",{"data-svelte-h":!0}),J(js)!=="svelte-1vcs1t4"&&(js.textContent=Sl),Jl=n(s),p(Js.$$.fragment,s),ml=n(s),rs=j(s,"P",{}),Xl(rs).forEach(t),this.h()},h(){_l(T,"name","hf:doc:metadata"),_l(T,"content",Ll)},m(s,l){Fl(document.head,T),e(s,Ts,l),e(s,ms,l),e(s,ws,l),y(w,s,l),e(s,ds,l),y(d,s,l),e(s,hs,l),e(s,h,l),e(s,us,l),e(s,u,l),e(s,Is,l),y(I,s,l),e(s,Cs,l),y(C,s,l),e(s,fs,l),y(f,s,l),e(s,gs,l),e(s,g,l),e(s,bs,l),e(s,b,l),e(s,Bs,l),y(B,s,l),e(s,$s,l),y($,s,l),e(s,As,l),y(A,s,l),e(s,Zs,l),e(s,Z,l),e(s,ks,l),e(s,k,l),e(s,Qs,l),y(Q,s,l),e(s,Vs,l),y(V,s,l),e(s,Es,l),y(E,s,l),e(s,Rs,l),e(s,R,l),e(s,Ss,l),e(s,S,l),e(s,Xs,l),y(X,s,l),e(s,_s,l),y(_,s,l),e(s,Ws,l),y(W,s,l),e(s,xs,l),e(s,x,l),e(s,Gs,l),e(s,G,l),e(s,qs,l),y(q,s,l),e(s,Ns,l),y(N,s,l),e(s,Hs,l),e(s,H,l),e(s,Fs,l),y(F,s,l),e(s,zs,l),e(s,z,l),e(s,Ys,l),y(Y,s,l),e(s,vs,l),y(v,s,l),e(s,Ls,l),y(L,s,l),e(s,Ks,l),e(s,K,l),e(s,Ds,l),y(D,s,l),e(s,Os,l),y(O,s,l),e(s,Ps,l),e(s,P,l),e(s,sl,l),y(ss,s,l),e(s,ll,l),e(s,ls,l),e(s,tl,l),y(ts,s,l),e(s,el,l),y(es,s,l),e(s,al,l),e(s,as,l),e(s,nl,l),y(ns,s,l),e(s,Ml,l),e(s,Ms,l),e(s,pl,l),y(ps,s,l),e(s,yl,l),y(ys,s,l),e(s,il,l),y(is,s,l),e(s,ol,l),y(os,s,l),e(s,Ul,l),y(Us,s,l),e(s,cl,l),e(s,cs,l),e(s,jl,l),e(s,js,l),e(s,Jl,l),y(Js,s,l),e(s,ml,l),e(s,rs,l),rl=!0},p:xl,i(s){rl||(i(w.$$.fragment,s),i(d.$$.fragment,s),i(I.$$.fragment,s),i(C.$$.fragment,s),i(f.$$.fragment,s),i(B.$$.fragment,s),i($.$$.fragment,s),i(A.$$.fragment,s),i(Q.$$.fragment,s),i(V.$$.fragment,s),i(E.$$.fragment,s),i(X.$$.fragment,s),i(_.$$.fragment,s),i(W.$$.fragment,s),i(q.$$.fragment,s),i(N.$$.fragment,s),i(F.$$.fragment,s),i(Y.$$.fragment,s),i(v.$$.fragment,s),i(L.$$.fragment,s),i(D.$$.fragment,s),i(O.$$.fragment,s),i(ss.$$.fragment,s),i(ts.$$.fragment,s),i(es.$$.fragment,s),i(ns.$$.fragment,s),i(ps.$$.fragment,s),i(ys.$$.fragment,s),i(is.$$.fragment,s),i(os.$$.fragment,s),i(Us.$$.fragment,s),i(Js.$$.fragment,s),rl=!0)},o(s){o(w.$$.fragment,s),o(d.$$.fragment,s),o(I.$$.fragment,s),o(C.$$.fragment,s),o(f.$$.fragment,s),o(B.$$.fragment,s),o($.$$.fragment,s),o(A.$$.fragment,s),o(Q.$$.fragment,s),o(V.$$.fragment,s),o(E.$$.fragment,s),o(X.$$.fragment,s),o(_.$$.fragment,s),o(W.$$.fragment,s),o(q.$$.fragment,s),o(N.$$.fragment,s),o(F.$$.fragment,s),o(Y.$$.fragment,s),o(v.$$.fragment,s),o(L.$$.fragment,s),o(D.$$.fragment,s),o(O.$$.fragment,s),o(ss.$$.fragment,s),o(ts.$$.fragment,s),o(es.$$.fragment,s),o(ns.$$.fragment,s),o(ps.$$.fragment,s),o(ys.$$.fragment,s),o(is.$$.fragment,s),o(os.$$.fragment,s),o(Us.$$.fragment,s),o(Js.$$.fragment,s),rl=!1},d(s){s&&(t(Ts),t(ms),t(ws),t(ds),t(hs),t(h),t(us),t(u),t(Is),t(Cs),t(fs),t(gs),t(g),t(bs),t(b),t(Bs),t($s),t(As),t(Zs),t(Z),t(ks),t(k),t(Qs),t(Vs),t(Es),t(Rs),t(R),t(Ss),t(S),t(Xs),t(_s),t(Ws),t(xs),t(x),t(Gs),t(G),t(qs),t(Ns),t(Hs),t(H),t(Fs),t(zs),t(z),t(Ys),t(vs),t(Ls),t(Ks),t(K),t(Ds),t(Os),t(Ps),t(P),t(sl),t(ll),t(ls),t(tl),t(el),t(al),t(as),t(nl),t(Ml),t(Ms),t(pl),t(yl),t(il),t(ol),t(Ul),t(cl),t(cs),t(jl),t(js),t(Jl),t(ml),t(rs)),t(T),U(w,s),U(d,s),U(I,s),U(C,s),U(f,s),U(B,s),U($,s),U(A,s),U(Q,s),U(V,s),U(E,s),U(X,s),U(_,s),U(W,s),U(q,s),U(N,s),U(F,s),U(Y,s),U(v,s),U(L,s),U(D,s),U(O,s),U(ss,s),U(ts,s),U(es,s),U(ns,s),U(ps,s),U(ys,s),U(is,s),U(os,s),U(Us,s),U(Js,s)}}}const Ll='{"title":"Tools and Sandboxing in Detail","local":"tools-and-sandboxing-in-detail","sections":[{"title":"The Four Tools","local":"the-four-tools","sections":[{"title":"1. list_dir(path) — List Files","local":"1-listdirpath--list-files","sections":[],"depth":3},{"title":"2. read_file(path, max_chars) — Read File","local":"2-readfilepath-maxchars--read-file","sections":[],"depth":3},{"title":"3. write_file(path, content) — Write File","local":"3-writefilepath-content--write-file","sections":[],"depth":3},{"title":"4. exec_cmd(args) — Execute Shell Command","local":"4-execcmdargs--execute-shell-command","sections":[],"depth":3}],"depth":2},{"title":"Path Confinement: safe_path()","local":"path-confinement-safepath","sections":[],"depth":2},{"title":"Execution Sandboxing","local":"execution-sandboxing","sections":[{"title":"Limited Global Scope","local":"limited-global-scope","sections":[],"depth":3},{"title":"Error Containment","local":"error-containment","sections":[],"depth":3}],"depth":2},{"title":"Commercial Agents vs. Nano Harness","local":"commercial-agents-vs-nano-harness","sections":[],"depth":2},{"title":"Designing Custom Tools","local":"designing-custom-tools","sections":[{"title":"Good Tool Design","local":"good-tool-design","sections":[],"depth":3},{"title":"Tool Anti-Patterns","local":"tool-anti-patterns","sections":[],"depth":3}],"depth":2},{"title":"Key Takeaways","local":"key-takeaways","sections":[],"depth":2}],"depth":1}';function Kl(Tl){return Gl(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class lt extends ql{constructor(T){super(),Nl(this,T,Kl,vl,Wl,{})}}export{lt as component}; | |
Xet Storage Details
- Size:
- 39.3 kB
- Xet hash:
- ba30a2ebe8002fa9ad853402ee4b0347b7e2dc6c7640a10e307a9dbc36d155a6
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.