Buckets:
| import{s as Dt,n as Kt,o as te}from"../chunks/scheduler.4048030c.js";import{S as ee,i as se,e as i,s as l,c as r,h as ne,a as o,d as s,b as a,f as Vt,j as p,g as d,k as Pt,l as le,m as n,n as h,t as m,o as u,p as f}from"../chunks/index.5d0b9360.js";import{C as ae,H as c,E as ie}from"../chunks/MermaidChart.svelte_svelte_type_style_lang.8dfdfd7d.js";import{C as Ut}from"../chunks/CodeBlock.da9970c4.js";function oe(Lt){let g,V,O,D,w,K,y,tt,T,Bt="Mainstream agent frameworks (Codex, Claude Code, OpenCode) hide the loop that makes them work, which is great for production use, but not for learning.",et,x,Zt="Nano Harness is a ~220-line Python agent built for reading, not production. It shows the system prompt, the step loop, tool execution, message history, error handling, and sandboxing in one file.",st,$,Nt="<p>nano_harness is a learning tool and not intended for production use. It’s just a fun way to understand how agents work under the hood. Do not use it for real work!</p>",nt,M,lt,b,Ft="Learning from scratch is a great way to understand how anything works under the hood.",at,v,zt="Reading a minimal harness makes the design choices legible: when to retry, how to parse output, how to handle errors, and where the security boundary sits. This unit uses <code>zai-org/GLM-5.1</code> via Hugging Face Inference Providers as the single model, so the only moving parts are the loop and the tools.",it,C,ot,j,qt="Nano Harness is a ~220-line Python agent framework that:",rt,k,Wt="<li><strong>Takes a task</strong> — “Inspect the workspace and provide a summary”</li> <li><strong>Calls an LLM</strong> — Uses OpenAI-compatible API (defaults to HF router)</li> <li><strong>Generates Python code</strong> — Model outputs executable Python code that will help complete the task</li> <li><strong>Executes safely</strong> — In a sandboxed environment with allowed tools</li> <li><strong>Observes results</strong> — stdout, stderr, exceptions, or a captured final answer</li> <li><strong>Updates context</strong> — Feeds observations back to the model</li> <li><strong>Repeats</strong> — Until the task is done or we hit step limit (we’re assuming 50 steps in our implementation)</li>",pt,J,dt,I,ht,_,Gt="Instead of returning JSON or text, the model outputs Python code:",mt,H,ut,P,Rt="The agent parses and executes it.",ft,U,ct,L,At="Four tools available:",gt,B,Et="<thead><tr><th>Tool</th> <th>What It Does</th> <th>Security</th></tr></thead> <tbody><tr><td><code>list_dir(path)</code></td> <td>List directory contents</td> <td>Path confinement</td></tr> <tr><td><code>read_file(path, max_chars)</code></td> <td>Read file</td> <td>Path confinement, size limit</td></tr> <tr><td><code>write_file(path, content)</code></td> <td>Create/modify file</td> <td>Path confinement, disabled by default</td></tr> <tr><td><code>exec_cmd(args)</code></td> <td>Run shell command</td> <td>Allowlist (only: ls, cat, pwd, echo, head, tail, wc, rg)</td></tr></tbody>",$t,Z,wt,N,Xt="<li>All file access confined to workspace</li> <li>Commands restricted to allowlist</li> <li>Output size limited to prevent context overflow</li> <li>Timeouts prevent hanging</li>",yt,F,Tt,z,St="The harness defaults to the Hugging Face router, which exposes an OpenAI-compatible <code>/v1</code> surface backed by Inference Providers:",xt,q,Mt,W,bt,G,Qt="Nano Harness implements the core loop:",vt,R,Ct,A,jt,E,Ot="This unit walks through the agent loop code piece by piece, explains how the tools are designed and sandboxed, extends the harness with <code>web_fetch</code> and HF Hub search, and runs it against <code>zai-org/GLM-5.1</code> through Hugging Face Inference Providers.",kt,X,Jt,S,Yt="Basic Python, familiarity with HTTP APIs and sandboxing, and an HF token with access to Inference Providers.",It,Q,_t,Y,Ht;return w=new ae({props:{containerStyle:"float: right; margin-left: 10px; display: inline-flex; position: relative; z-index: 10;"}}),y=new c({props:{title:"Introduction to Nano Harness",local:"introduction-to-nano-harness",headingTag:"h1"}}),M=new c({props:{title:"Why start from scratch?",local:"why-start-from-scratch",headingTag:"h2"}}),C=new c({props:{title:"What is Nano Harness?",local:"what-is-nano-harness",headingTag:"h2"}}),J=new c({props:{title:"Key Features",local:"key-features",headingTag:"h2"}}),I=new c({props:{title:"Code-First Agent",local:"code-first-agent",headingTag:"h3"}}),H=new Ut({props:{code:"JTIzJTIwTW9kZWwlMjBzYXlzJTNBJTBBZmlsZXMlMjAlM0QlMjBsaXN0X2RpciglMjIuJTIyKSUwQW1vZGVscyUyMCUzRCUyMHJlYWRfZmlsZSglMjJtb2RlbHMudHh0JTIyKSUwQWZpbmFsX2Fuc3dlciglMjJGaWxlcyUzQSU1Q24lMjIlMjAlMkIlMjAlMjIlNUNuJTIyLmpvaW4oZmlsZXMpJTIwJTJCJTIwJTIyJTVDbiU1Q25tb2RlbHMudHh0JTNBJTVDbiUyMiUyMCUyQiUyMG1vZGVscyk=",highlighted:`<span class="hljs-comment"># Model says:</span> | |
| files = list_dir(<span class="hljs-string">"."</span>) | |
| models = read_file(<span class="hljs-string">"models.txt"</span>) | |
| final_answer(<span class="hljs-string">"Files:\\n"</span> + <span class="hljs-string">"\\n"</span>.join(files) + <span class="hljs-string">"\\n\\nmodels.txt:\\n"</span> + models)`,wrap:!1}}),U=new c({props:{title:"Constrained Tools",local:"constrained-tools",headingTag:"h3"}}),Z=new c({props:{title:"Sandboxed Execution",local:"sandboxed-execution",headingTag:"h3"}}),F=new c({props:{title:"Model via Hugging Face Inference Providers",local:"model-via-hugging-face-inference-providers",headingTag:"h3"}}),q=new Ut({props:{code:"ZXhwb3J0JTIwTkFOT19NT0RFTCUzRCUyMnphaS1vcmclMkZHTE0tNS4xJTIyJTBBZXhwb3J0JTIwSEZfVE9LRU4lM0QlMjJoZl8uLi4lMjI=",highlighted:`<span class="hljs-built_in">export</span> NANO_MODEL=<span class="hljs-string">"zai-org/GLM-5.1"</span> | |
| <span class="hljs-built_in">export</span> HF_TOKEN=<span class="hljs-string">"hf_..."</span>`,wrap:!1}}),W=new c({props:{title:"The Agentic Loop",local:"the-agentic-loop",headingTag:"h2"}}),R=new Ut({props:{code:"MS4lMjBDYWxsJTIwTExNJTIwd2l0aCUyMHRhc2slMjAlMkIlMjBtZXNzYWdlJTIwaGlzdG9yeSUwQTIuJTIwUGFyc2UlMjBtb2RlbCUyMG91dHB1dCUyMGFzJTIwUHl0aG9uJTIwY29kZSUwQTMuJTIwRXhlY3V0ZSUyMFB5dGhvbiUyMCh3aXRoJTIwdG9vbHMlMjBhdmFpbGFibGUpJTBBNC4lMjBDb2xsZWN0JTIwc3Rkb3V0JTJDJTIwc3RkZXJyJTJDJTIwZXhjZXB0aW9ucyUwQTUuJTIwQXBwZW5kJTIwb2JzZXJ2YXRpb24lMjB0byUyMG1lc3NhZ2UlMjBoaXN0b3J5JTBBNi4lMjBSZXBlYXQlMjAobWF4JTIwNTAlMjBzdGVwcyklMEE3LiUyMERvbmUlMjB3aGVuJTNBJTIwZmluYWxfYW5zd2VyKCklMjBjYWxsZWQlMjBvciUyMG1heCUyMHN0ZXBzJTIwcmVhY2hlZA==",highlighted:`<span class="hljs-number">1.</span> <span class="hljs-keyword">Call</span> LLM <span class="hljs-keyword">with</span> task + message history | |
| <span class="hljs-number">2.</span> Parse model output <span class="hljs-keyword">as</span> Python code | |
| <span class="hljs-number">3.</span> <span class="hljs-keyword">Execute</span> Python (<span class="hljs-keyword">with</span> tools available) | |
| <span class="hljs-number">4.</span> Collect stdout, stderr, exceptions | |
| <span class="hljs-number">5.</span> Append observation <span class="hljs-keyword">to</span> message history | |
| <span class="hljs-number">6.</span> Repeat (max <span class="hljs-number">50</span> steps) | |
| <span class="hljs-number">7.</span> Done <span class="hljs-keyword">when</span>: final_answer() <span class="hljs-keyword">called</span> <span class="hljs-keyword">or</span> max steps reached`,wrap:!1}}),A=new c({props:{title:"What You’ll Learn",local:"what-youll-learn",headingTag:"h2"}}),X=new c({props:{title:"Prerequisites",local:"prerequisites",headingTag:"h2"}}),Q=new ie({props:{source:"https://github.com/huggingface/context-course/blob/main/units/en/unit6/introduction.mdx"}}),{c(){g=i("meta"),V=l(),O=i("p"),D=l(),r(w.$$.fragment),K=l(),r(y.$$.fragment),tt=l(),T=i("p"),T.textContent=Bt,et=l(),x=i("p"),x.textContent=Zt,st=l(),$=i("blockquote"),$.innerHTML=Nt,nt=l(),r(M.$$.fragment),lt=l(),b=i("p"),b.textContent=Ft,at=l(),v=i("p"),v.innerHTML=zt,it=l(),r(C.$$.fragment),ot=l(),j=i("p"),j.textContent=qt,rt=l(),k=i("ol"),k.innerHTML=Wt,pt=l(),r(J.$$.fragment),dt=l(),r(I.$$.fragment),ht=l(),_=i("p"),_.textContent=Gt,mt=l(),r(H.$$.fragment),ut=l(),P=i("p"),P.textContent=Rt,ft=l(),r(U.$$.fragment),ct=l(),L=i("p"),L.textContent=At,gt=l(),B=i("table"),B.innerHTML=Et,$t=l(),r(Z.$$.fragment),wt=l(),N=i("ul"),N.innerHTML=Xt,yt=l(),r(F.$$.fragment),Tt=l(),z=i("p"),z.innerHTML=St,xt=l(),r(q.$$.fragment),Mt=l(),r(W.$$.fragment),bt=l(),G=i("p"),G.textContent=Qt,vt=l(),r(R.$$.fragment),Ct=l(),r(A.$$.fragment),jt=l(),E=i("p"),E.innerHTML=Ot,kt=l(),r(X.$$.fragment),Jt=l(),S=i("p"),S.textContent=Yt,It=l(),r(Q.$$.fragment),_t=l(),Y=i("p"),this.h()},l(t){const e=ne("svelte-u9bgzb",document.head);g=o(e,"META",{name:!0,content:!0}),e.forEach(s),V=a(t),O=o(t,"P",{}),Vt(O).forEach(s),D=a(t),p(w.$$.fragment,t),K=a(t),p(y.$$.fragment,t),tt=a(t),T=o(t,"P",{"data-svelte-h":!0}),d(T)!=="svelte-e1nkgv"&&(T.textContent=Bt),et=a(t),x=o(t,"P",{"data-svelte-h":!0}),d(x)!=="svelte-9fex05"&&(x.textContent=Zt),st=a(t),$=o(t,"BLOCKQUOTE",{class:!0,"data-svelte-h":!0}),d($)!=="svelte-1yaushg"&&($.innerHTML=Nt),nt=a(t),p(M.$$.fragment,t),lt=a(t),b=o(t,"P",{"data-svelte-h":!0}),d(b)!=="svelte-lwifxz"&&(b.textContent=Ft),at=a(t),v=o(t,"P",{"data-svelte-h":!0}),d(v)!=="svelte-k6bg40"&&(v.innerHTML=zt),it=a(t),p(C.$$.fragment,t),ot=a(t),j=o(t,"P",{"data-svelte-h":!0}),d(j)!=="svelte-gzknv8"&&(j.textContent=qt),rt=a(t),k=o(t,"OL",{"data-svelte-h":!0}),d(k)!=="svelte-z5kfuu"&&(k.innerHTML=Wt),pt=a(t),p(J.$$.fragment,t),dt=a(t),p(I.$$.fragment,t),ht=a(t),_=o(t,"P",{"data-svelte-h":!0}),d(_)!=="svelte-1zerse"&&(_.textContent=Gt),mt=a(t),p(H.$$.fragment,t),ut=a(t),P=o(t,"P",{"data-svelte-h":!0}),d(P)!=="svelte-1rw7670"&&(P.textContent=Rt),ft=a(t),p(U.$$.fragment,t),ct=a(t),L=o(t,"P",{"data-svelte-h":!0}),d(L)!=="svelte-1yp1ity"&&(L.textContent=At),gt=a(t),B=o(t,"TABLE",{"data-svelte-h":!0}),d(B)!=="svelte-ghopt7"&&(B.innerHTML=Et),$t=a(t),p(Z.$$.fragment,t),wt=a(t),N=o(t,"UL",{"data-svelte-h":!0}),d(N)!=="svelte-410jya"&&(N.innerHTML=Xt),yt=a(t),p(F.$$.fragment,t),Tt=a(t),z=o(t,"P",{"data-svelte-h":!0}),d(z)!=="svelte-1nl9jqm"&&(z.innerHTML=St),xt=a(t),p(q.$$.fragment,t),Mt=a(t),p(W.$$.fragment,t),bt=a(t),G=o(t,"P",{"data-svelte-h":!0}),d(G)!=="svelte-10drajq"&&(G.textContent=Qt),vt=a(t),p(R.$$.fragment,t),Ct=a(t),p(A.$$.fragment,t),jt=a(t),E=o(t,"P",{"data-svelte-h":!0}),d(E)!=="svelte-wstrrq"&&(E.innerHTML=Ot),kt=a(t),p(X.$$.fragment,t),Jt=a(t),S=o(t,"P",{"data-svelte-h":!0}),d(S)!=="svelte-1uhzkch"&&(S.textContent=Yt),It=a(t),p(Q.$$.fragment,t),_t=a(t),Y=o(t,"P",{}),Vt(Y).forEach(s),this.h()},h(){Pt(g,"name","hf:doc:metadata"),Pt(g,"content",re),Pt($,"class","warning")},m(t,e){le(document.head,g),n(t,V,e),n(t,O,e),n(t,D,e),h(w,t,e),n(t,K,e),h(y,t,e),n(t,tt,e),n(t,T,e),n(t,et,e),n(t,x,e),n(t,st,e),n(t,$,e),n(t,nt,e),h(M,t,e),n(t,lt,e),n(t,b,e),n(t,at,e),n(t,v,e),n(t,it,e),h(C,t,e),n(t,ot,e),n(t,j,e),n(t,rt,e),n(t,k,e),n(t,pt,e),h(J,t,e),n(t,dt,e),h(I,t,e),n(t,ht,e),n(t,_,e),n(t,mt,e),h(H,t,e),n(t,ut,e),n(t,P,e),n(t,ft,e),h(U,t,e),n(t,ct,e),n(t,L,e),n(t,gt,e),n(t,B,e),n(t,$t,e),h(Z,t,e),n(t,wt,e),n(t,N,e),n(t,yt,e),h(F,t,e),n(t,Tt,e),n(t,z,e),n(t,xt,e),h(q,t,e),n(t,Mt,e),h(W,t,e),n(t,bt,e),n(t,G,e),n(t,vt,e),h(R,t,e),n(t,Ct,e),h(A,t,e),n(t,jt,e),n(t,E,e),n(t,kt,e),h(X,t,e),n(t,Jt,e),n(t,S,e),n(t,It,e),h(Q,t,e),n(t,_t,e),n(t,Y,e),Ht=!0},p:Kt,i(t){Ht||(m(w.$$.fragment,t),m(y.$$.fragment,t),m(M.$$.fragment,t),m(C.$$.fragment,t),m(J.$$.fragment,t),m(I.$$.fragment,t),m(H.$$.fragment,t),m(U.$$.fragment,t),m(Z.$$.fragment,t),m(F.$$.fragment,t),m(q.$$.fragment,t),m(W.$$.fragment,t),m(R.$$.fragment,t),m(A.$$.fragment,t),m(X.$$.fragment,t),m(Q.$$.fragment,t),Ht=!0)},o(t){u(w.$$.fragment,t),u(y.$$.fragment,t),u(M.$$.fragment,t),u(C.$$.fragment,t),u(J.$$.fragment,t),u(I.$$.fragment,t),u(H.$$.fragment,t),u(U.$$.fragment,t),u(Z.$$.fragment,t),u(F.$$.fragment,t),u(q.$$.fragment,t),u(W.$$.fragment,t),u(R.$$.fragment,t),u(A.$$.fragment,t),u(X.$$.fragment,t),u(Q.$$.fragment,t),Ht=!1},d(t){t&&(s(V),s(O),s(D),s(K),s(tt),s(T),s(et),s(x),s(st),s($),s(nt),s(lt),s(b),s(at),s(v),s(it),s(ot),s(j),s(rt),s(k),s(pt),s(dt),s(ht),s(_),s(mt),s(ut),s(P),s(ft),s(ct),s(L),s(gt),s(B),s($t),s(wt),s(N),s(yt),s(Tt),s(z),s(xt),s(Mt),s(bt),s(G),s(vt),s(Ct),s(jt),s(E),s(kt),s(Jt),s(S),s(It),s(_t),s(Y)),s(g),f(w,t),f(y,t),f(M,t),f(C,t),f(J,t),f(I,t),f(H,t),f(U,t),f(Z,t),f(F,t),f(q,t),f(W,t),f(R,t),f(A,t),f(X,t),f(Q,t)}}}const re='{"title":"Introduction to Nano Harness","local":"introduction-to-nano-harness","sections":[{"title":"Why start from scratch?","local":"why-start-from-scratch","sections":[],"depth":2},{"title":"What is Nano Harness?","local":"what-is-nano-harness","sections":[],"depth":2},{"title":"Key Features","local":"key-features","sections":[{"title":"Code-First Agent","local":"code-first-agent","sections":[],"depth":3},{"title":"Constrained Tools","local":"constrained-tools","sections":[],"depth":3},{"title":"Sandboxed Execution","local":"sandboxed-execution","sections":[],"depth":3},{"title":"Model via Hugging Face Inference Providers","local":"model-via-hugging-face-inference-providers","sections":[],"depth":3}],"depth":2},{"title":"The Agentic Loop","local":"the-agentic-loop","sections":[],"depth":2},{"title":"What You’ll Learn","local":"what-youll-learn","sections":[],"depth":2},{"title":"Prerequisites","local":"prerequisites","sections":[],"depth":2}],"depth":1}';function pe(Lt){return te(()=>{new URLSearchParams(window.location.search).get("fw")}),[]}class fe extends ee{constructor(g){super(),se(this,g,pe,oe,Dt,{})}}export{fe as component}; | |
Xet Storage Details
- Size:
- 13.5 kB
- Xet hash:
- 31ef7c2020a7996071903d1fd40d98a959a34be752721e01a28be82374276da6
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.