From c63bfaa585a6521d8da945e55c7d22d7e470b417 Mon Sep 17 00:00:00 2001 From: westey <164392973+westey-m@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:31:47 +0000 Subject: [PATCH 1/4] Python/.Net: Agent Harness blog post accompanying samples part 3 --- dotnet/00-build-your-own-claw-overview.webp | Bin 0 -> 38524 bytes dotnet/01-meet-your-claw.webp | Bin 0 -> 35778 bytes dotnet/02-working-with-your-data-safely.webp | Bin 0 -> 32908 bytes dotnet/agent-framework-dotnet.slnx | 1 + .../Claw_Step03_ScalingCapabilities.csproj | 31 ++ .../FoundrySkills.cs | 60 ++++ .../Program.cs | 224 ++++++++++++ .../Claw_Step03_ScalingCapabilities/README.md | 80 +++++ .../ResearchAgent.cs | 30 ++ .../StockTools.cs | 60 ++++ .../SubprocessScriptRunner.cs | 177 +++++++++ .../TradingTools.cs | 55 +++ .../skills/risk-scoring/SKILL.md | 18 + .../risk-scoring/references/risk-bands.md | 27 ++ .../skills/risk-scoring/scripts/risk_score.py | 54 +++ .../skills/valuation/SKILL.md | 17 + .../valuation/references/valuation-guide.md | 28 ++ .../valuation/scripts/valuation_metrics.py | 49 +++ .../working/confirmations/2025-06-21_nvda.txt | 6 + .../working/confirmations/SPY sell.txt | 6 + .../working/confirmations/conf_AAPL.txt | 6 + .../confirmations/copy of trade (3).txt | 6 + .../working/confirmations/googl-jan.txt | 6 + .../confirmations/trade confirmation 1.txt | 6 + .../working/portfolio.csv | 7 + dotnet/samples/02-agents/Harness/README.md | 1 + .../harness/build_your_own_claw/README.md | 59 +++ .../claw_step03_scaling_capabilities.py | 339 ++++++++++++++++++ .../skills/risk-scoring/SKILL.md | 18 + .../risk-scoring/references/risk-bands.md | 27 ++ .../skills/risk-scoring/scripts/risk_score.py | 54 +++ .../skills/valuation/SKILL.md | 17 + .../valuation/references/valuation-guide.md | 28 ++ .../valuation/scripts/valuation_metrics.py | 49 +++ .../subprocess_script_runner.py | 77 ++++ .../working/confirmations/2025-06-21_nvda.txt | 6 + .../working/confirmations/SPY sell.txt | 6 + .../working/confirmations/conf_AAPL.txt | 6 + .../confirmations/copy of trade (3).txt | 6 + .../working/confirmations/googl-jan.txt | 6 + .../confirmations/trade confirmation 1.txt | 6 + 41 files changed, 1659 insertions(+) create mode 100644 dotnet/00-build-your-own-claw-overview.webp create mode 100644 dotnet/01-meet-your-claw.webp create mode 100644 dotnet/02-working-with-your-data-safely.webp create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Claw_Step03_ScalingCapabilities.csproj create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/FoundrySkills.cs create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Program.cs create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/README.md create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/ResearchAgent.cs create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/StockTools.cs create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/SubprocessScriptRunner.cs create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/TradingTools.cs create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/SKILL.md create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/references/risk-bands.md create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/scripts/risk_score.py create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/SKILL.md create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/references/valuation-guide.md create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/scripts/valuation_metrics.py create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/2025-06-21_nvda.txt create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/SPY sell.txt create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/conf_AAPL.txt create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/copy of trade (3).txt create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/googl-jan.txt create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/trade confirmation 1.txt create mode 100644 dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/portfolio.csv create mode 100644 python/samples/02-agents/harness/build_your_own_claw/claw_step03_scaling_capabilities.py create mode 100644 python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/SKILL.md create mode 100644 python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/references/risk-bands.md create mode 100644 python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/scripts/risk_score.py create mode 100644 python/samples/02-agents/harness/build_your_own_claw/skills/valuation/SKILL.md create mode 100644 python/samples/02-agents/harness/build_your_own_claw/skills/valuation/references/valuation-guide.md create mode 100644 python/samples/02-agents/harness/build_your_own_claw/skills/valuation/scripts/valuation_metrics.py create mode 100644 python/samples/02-agents/harness/build_your_own_claw/subprocess_script_runner.py create mode 100644 python/samples/02-agents/harness/build_your_own_claw/working/confirmations/2025-06-21_nvda.txt create mode 100644 python/samples/02-agents/harness/build_your_own_claw/working/confirmations/SPY sell.txt create mode 100644 python/samples/02-agents/harness/build_your_own_claw/working/confirmations/conf_AAPL.txt create mode 100644 python/samples/02-agents/harness/build_your_own_claw/working/confirmations/copy of trade (3).txt create mode 100644 python/samples/02-agents/harness/build_your_own_claw/working/confirmations/googl-jan.txt create mode 100644 python/samples/02-agents/harness/build_your_own_claw/working/confirmations/trade confirmation 1.txt diff --git a/dotnet/00-build-your-own-claw-overview.webp b/dotnet/00-build-your-own-claw-overview.webp new file mode 100644 index 0000000000000000000000000000000000000000..a373eb9ed13f4181e364427fd7b7558c5b053703 GIT binary patch literal 38524 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 Mxo>*~h;IM@0QVQ{xBvhE literal 0 HcmV?d00001 diff --git a/dotnet/01-meet-your-claw.webp b/dotnet/01-meet-your-claw.webp new file mode 100644 index 0000000000000000000000000000000000000000..52e281d51c1dcec985236c013a69fd832aa0b675 GIT binary patch literal 35778 zcmV)2K+L~VNk&GxivR#uMM6+kP&gp2ivR#{cLJROD!>Go0zNSqi$o$Jp&}uZ86ZFg z31@En6ftEx4aXsR{;Qr$Kss8!@AJ_x>@A@zP z-|>C6{gQvs|Lyh{{pIxH{oDW5^2hzF{#WhK|4(_(|G)Hoz(4$ZY5xHK|J8rszx#i% z|3>|e`FY~6*+0O3(0_9G56(}eJ%sqa{KNeJXP+JYpPE0({>T0Q`ycsF_CMVJbUyWe zQU5Fauj@yff0+L}{=@SZ{Ex^l;(y6MzyELj!v7`vS@jbJPNa8d)EC}Auz#=r5&l#D zfB2u1-+cc){nypcuixtbHowFDfPXsvmHvPGPxycRU)q2F``>s>`Y*5-^B?M8?LWr< zg#EPoZ~j~Um-x^1-?pCSKSBQ)|6Ba$`yY`H=bzXA;{SvHL;Gp}|NsBo&;QTf50Rg> zzx_SW|6>383o5XdOeJww?P}oRLGv>SREYgE7KOR@y)?pwbpPvU?#W%RC`R9nN&5?c zP5q)PZ?rsRqn(#X_H~7iXIYxIfyqN|ZH@2$_vkjtF*N7cAs;j}xqCVHkJT#%bDk^1 z;|&)z0vEu__zNjiCYpJeJFM>;Yw+k`syDRDxV$EtsjVd6?UT-C{Fnc0C_; zq0vH%J;O}9b1zO+H&X`CE{k;TJa`@)B~(XOs~%h)iOMY54i>Dhq!&<3l6K|h%4rDR zKxOSLWF$NP8J9f})D-8sC8*AEE*O$pxg}G1mbPHcKyZO+%+CWihoVuancy-$Rjjb_ zdZB7g<3nTe2L@6T=>z~@H|1_6auHn7slP?OZhHZ~DuOoey?{`rR6?>g)~5 z2cLh~S;`&@m29fVgsr$IT~L5x5;(MiBrttR|9|}P?oXp8Ua_`IX2V-TZ0GSf3FBhuv914magzl9+Tvc1k6q@eLz@(H1gv8M!DjDa4Qd zM_RK1<4JuaziA)%BuS*;ooCROZKAQ;?yA*(QHkYVgp$~6Si=}E@ur8)7}DmJyCU6p z&^;q#o!X!fK;_K4WL4p!$Mb8FUF@pE?~07Axg>#C-`K&mZ|$7cCLv}9RL;oz8k5U) z<%2I__5msgj2R-v>K2b?sS1$xx76x=1+cUyNp*Ar%?A4ppsmuf8Wmow9Dc!VE>IGcH3N~ah>KM_>kdr(7hNaJe zBF^2GxEL}>|EV89hf3^?{cT;b>jkiEq6K)}$i9515Rhc+;hH2>EeK%g=*|IecwWIw z9a|^>f)?Fj2Dphk*0#nXPrMS#^lm|>Ut>W}YZkW3ukqf_ZiSgZ#t3s)-L=WEluiy` zjy|uT5E2Wyy8L^WjgHtKcqQjViHNU+>+VzSNF5uc*7hIXHP7e{c^)cDDx~6G`!Q@^ zmWq%*bs@6^q%nOr*CQZNvljZ~1Mbq;RpKH2774DaiZ+{sux^9Jnes!xCuj2fg)< zFnX(+VN+1-`%DK)+P-741UTh7rvUeWsdJFAQg~;5pHc@k@yJDWrlJ7^X~6DEKmWIy z9kf&1^)xxVn8Fd!k@8i=Q$?0+Rfv=5?aorMLrHV%>N#<2_TT+Ih-c_>Ouv#Y$|&@+ zFcp>cyErwhvH$=7{PXDJW$q|LR-k9iLVITemkk+=z_a@Izcu~Kl7I;xFcvCBwM6Rv zmA0!bpWJ?zrKO?x&uk$nkf)QBqW(IkhX+oye0zSHw-B;!MOYOsqd4wCzyI>XB0u~i z+HP*Ja*d&|;clSOd)BfVpVsQt6Wu)=Ks1m6WvOqo4 z0SDt^lBy<`mAk9p$YekpFnrB=55Eo^Fz)XBvF40G?KEMI%4N83pGNjAVPU(04qK6x zsY$#hCzXg)IWe=7?|=8Mf-I83JvlitHvsBm-;IRb`iS|aONn9tn@Pld;{gssUHFHfz zp_0j)Bv8WRB*!VI!0>9L60QI8p>!0Uc#FAPWmoua)SViQbl3m6`Zx#O*N}!A5e?Iz z9WIR779tlGZ2RqfLR1K!v7nhYJdV z0TU~YR$>GX(gprjEIG&B04n=~F;pynQLd&0-O*OS_ zOi8?D?bQb&jc^dqqQb0?4~dlg1lp3!0);)2<%|;*ehn57DAiWWjXc~L(<`R7oW=k9 z2=I-!o`-VB5(T#PX?9ynqp@O`qe#z}Wv3;aG+XInBuToWlVTsT^j2f9&(j z(_A?2B^M0_RiUk8G*NWB3weT!JQqGQ9O>4{vLpSCeHiwKrK!;9pH0%Z%Lx&}U;@tg z1&g5AvmdDMrm{D;_9njsVzCqKTKqv1;>9wf@>fg@gWS=N`d7Ok`_>fA{f&F;0R_*Q zK@;QMZe@)hsIs0@g^tn_$TUjmbHYT&cIxt-*ga2{K}Pu5r2l*o=er2(>--!XiyzNf z@QlJVRoEYOwrOCMyw3XVO}N#T&X2I_7yD5D?ssS0``Ag*)-y1bD_o!Ha&GA5(NS#N z&6d@YfzW(rENz_n>aVKSDVg8BKCPAW(vq{v)Yi^Vt1|-ll5J^r-cdhU*T(z#Dg_$m z;2fQpO##%kG(V=rr_C#jfPr9Q$w}a1YGRQ%30LP~VHZPKi)frLB6<7x2fx2<=ukca z8BU?4QyN*E=@h;k`6v#jyX}nVr`;lEa=*zWwf!1p!Li%0gp(<3yKinKH|#aB1bzyW z-gU2+X#8GiAn7Ihoz>k(E`F2u z;*Jt&YarCR?Gh12$E~e410g@Cnmilp`dIo22e1W@p=oUN^lvRbJZGEi))1iS-2A?g zHAZk0haGjqC4p=s`{(j(%GA4NTMP;F?CcJZO#|9T@2}hrJT{=8}Ax2G% zF@?0$7VC#6{eZh>B3E;ZZ2pmXr%x~1uTY_xL_y;-Qe*9Vt`M_7B)(sycq{^|YncCO zaf87Vlo{e&7d^Ib6u19$E@fAJqv4Vw$C;r4dWm+#3C$s zC=P(Ubwg139+e|gy5kzy7vdr3{X6Xp))CtJ51ciX0!bMqF`2sz7>1a57>`&PVsonM z7SU|u=^O;$g3p9Tm@D7Szk5DLqQc4)o>~V#e*Juz>ftxzHIXjTzy%SXo&WRy@f-4# zMp?FOA_W7h>T*6l(QYm^hXts`_Z}7QNTO$AK;|-Jnb@ z$yt5-ugG?Xu4bWO&Y`O_2UU_w$ZBmxuNYsQOMQ&FG**o@B8AB_32m$i-!r_M$hgtr z!4B_}k&22^{?{f622H9n(=Bj2grL#K{)oX;BAl(16;^>J{ARKx=FNpmovxpVB>(^a z|Bm`YLI7!M|Dezm^ql&hNboktPk39YHP2pjbNUY{SY=&J^Tab}>CqBF0$HWBHhy-1 zYR`gk#|GWb(?tws765lqX%w(OpXP_8sAmm^fI=%aOJzJ-bTO}bB>DqKMpa|3Qv6t| zEuk~7eJnOuJtwe+-foYOZwmG1V_9|*fzqsZ|M*|+?egAspy?q|jsb~}N=T2$aaCni zUOT!z)2RVbW02KUpGtpp6?jA`d`&BS{W@ljGa0NFO03gv;3#v7zX(0{)Uv*xQ(tZDVfUV7ry$p1=Iau?{sS&;S4ZOCe7!Y0n;LcTa_NE!ZRC60Yn)sKokf zPw=gzBcg;9LjrcU6?Layfnz^*+QUVPi>W#M*m(*b_#{S|i1%>u!R<%0qqa2)U@}^_ zYwV13`7)H*{2%Km4~`X-^krJ3z%vLmsb_qj}~2$n7KQfc17{p4J^9%|o$qO6dW zlzZB1b7btsHFF0EsKm zHQi~~dzpd)aYpawb`k)o=vP$FfTX!XBoGb=VlXGytL+vY+6maOh{kraxA<(-7WV$; zTPl1&vF6s|SI#;f#Ut)uei|QR6`WpIQyL#4`%_Z1woUKK+u!_!_~1@DpO^#scoSfb z4Lw|fNU+v9hSA6MMw-jovl!~!-ly|x-h=qsa0IdVjfQG854*3WG=W+;j`uE|j^9v9 za&T$k5kIoIMwbY=77h_8WbxU2T-+2QE=8zDna;7d47K&OCy*%wS>Du zocQb*ynK}P!!KeurG1!3}x-y_$XwoB>w-D?|L@OzMjJIa?1JgM;3;_ zir7C#`;HKS!DO>F>m?MHmV9vo4wX+3^~`|vU>E5$6!L0{=^R@#jom+^qM9inj+5N| zC+ux=$2uOh4-(<$8n!4pIGP`%JoF36nerY-52yG1q=pj_MeVULM2Wkbr{%CW~x z!881J@?3WK@42d)L&xklM9WeLN%y{9zMg(>xX2nRpszuIbZGqm`S{sb>XfL^@VH|s zw`V0m)NQg%i3iQw>Kui6!M_NV+lu`9$o|IQLn%;i-jb=$n+zle989F$bm`?d?uv6) z$@`LBjXMwGa~cSbA*=n|X_8vsb#G`aj1Po_DUt{=6hGa@{>44rsMi1T`tv$x`n0h6-F}|x z1Hml6M&xn(1MnE*M$jx^ZDycF$$JPLTR2hVin9y#P8G&RBLogcRaGa1kT!R>qvj?$5}jh6UK9#-HsETkE(yf{r4PI*+9toLQRFtvFp0(2EHfPoeS9urtp)9~YjBTF);!Hop1tJoy}2 z9S6`wy1}e&wzP3%5k}@Q7z=_vwgH48xaP-6tWh>wj~h25i$j~YZai$6U z27gx%o=5+#$@>!iv0mJg5(I+Vb52JCsvrJb)gw+YseN`Jg+KgfZD}+WJKZ9?I@5Ev zK`#Y)Vg=S7M~|5~3M2F>70ekZ+Nmr7pVHVX8p#-8U`O`4)9FMEWc&So)aS)Yr5{=? z`jh2&bXw8Uv6Xp%v6p*|ek|PWjX;{(tQ9s4p2vM`^3^1^6MmjR9{b*(%>Z3T{zii> zgeRenUe?K|FTx9C@S)p$`!oA*`e(!=ZvbSXz>_*cJ?|e7mBwHvw>bg+Cf}eAOEJ1G z0rD4hhq0~k(>FjmOMqSX=-?4RJY9TcKuSv{xSG7AzWvD&3$&$V2-%1Z#SZ4`aMZk< zw&?s&yojzRSBvl9Ge3X!#4(g!rA93ps^h+}MnuPvGuq(?GQ`wV&!13|mnpD}N@KA) z%{pYJPJ1jqwsq#yFU{@khz3K&`|&@_J`yn7v1C!Vu%i1DSU0mB9eeF%r@oceRd{#P z6P@b)8iqWA$Q3rIJx3HNuF2JY|2ld2M*KB7Ukz+!Zo`r>zi=-=WrEp?l9>?rK9zb& zXkV2ipg18^j1m5Vs>Ft9>0s(~AX7;`@LEEb6P=&uHw;{iwtu<6lnL8S>XSq<(l^T)T@*qzLYVw7%aHD7~;E0T&>dT<5OVwbD#eeS!3V{XoZh>Wl%=phLAvTS28 zkdMc>I69O0x8lbBpib&2jz;8{@gYmiFRKeKr_HFhMA3DApL?{qYY>d!0m=YOUA{FN zO(7HXT94B0wXRm-hEvDdfAwAmM*?B_=P6_a4phg)^wIB+NpT9^WEjlFiGVw8<K7yS8=zjxR8uo^5$;*oTR&F>OL`8_tyljbhegrKFp(}{??#HME!G{@~V%RFi*Y!5<5s>31{zocK9h%5T}Q-A-U3A z>#&Wc7@ycsDFidheS0;gylWjdpY?P1apf;FFO&-BPFzu2K- z=i_McCN`9kC2ECm1=6W;-?3P0-7=8-!_eJZ@Hv!41h02Br(J|r_iUVv4Le0P&d?I#BJ(4fDma#$G`(*rN(4KzY;gB;1_Y8zTMDy93< zzAJ8tJy7W#ef`9OKh1rlm4l?-cZB8n1JZyTv)Ipyfvgu79blMjXOgCQhzRnA zoGu`xUXMr5{HD2VkQc|Dm@^BQ@MN=cK+pe{&3Fa^u@9Z6bA;Yub{$yeSnJF$gMM_) zQZ~bjbt1%_FNMI@u7-(f=^q;Oo74#!`H8Q1=hQlc1pCAHZs->!FPN44)pZZDnwtuBP=M?#ER674zke1uGZWOYyNqDf! z%Pg&`cm|irT~l*FA0PcupC?tnQNrx4q2d>e#eVg75aZq{Oxn5@y=nd)P_bV(&t4mk z>B8x9+&u%=Ci7s_-MDuFV$%YeF>h&-s&<{F(zKY{kr&{$w2+_tX?f)iO^?PZh8;Yw zbBv#p#A#>n%eX~jX$*9vj?MSae>X@zf_)@n(I9{q;^^IuXyi0M#J|4UN@79l0%^@2 zZ$tA3PvxYaUJ*u~T!mV6nZ=LSsVB;^yOooj*5>UDN$4uvo3f<*FE0h==?E zs;mbi!dXYGd;fGE4o)egP-$P!_!iOaCj;N$%Ob|_-Q1LEG+>(d)ZL)iRt^9Zr?fr5 zu246Yfwi&2g^g;i03kK}!z4^INxBr|v!oq6rra5Q5jfKNO8In#oz%av&qGeCa~-FT zhzx>Vu0#2Vpr0G$Hg;NWQ=lp-0~$G2zJ;{Jbm4%UKe-DyI}~__tCL{MK;Ryl2c?s{ z{;nyVBU1VP2R?)eD+LIx)n}qSYN_ZDVa4@LqvaM$dMoRswqW_yvuF=U!XF28TUe<3 zP}>}DGo+cQGY`g%V)}n}K8#DX_DWOKr|+#RwYvWW<6;Yo6j;)p5Vw7o(_EhGlHSJ* zlQf7jybN;yKS_fVf59Ct*Mz&tZrOB(+$qEAuGYJ`F#@eY5B4gb(6A4cC8{W^lvOEkw!i>#CsTgo$n%YAxjc1uaNRStqXiv7YST*C2B} zj1|4|IrdzY5<(z1lTXOnJdiLEzw_)9WxJy&SH}+4|KS6az9N$4D4)dAn`_&bKm#ZB zcgTi+8}nI>V3O0rkQzugpY&a`<5?VCm-p|$e)%pw#%pL;_KRv^$aT^v+vK6Ub}B0f z@4wQ<<^gPWldpV}g7_gA6Z%~yPE_g$o}NQeGR%~3pMCeX#!#;6buLn=1X+s$joSz5HNk=yHhEav^ zcpm7CV^Nik`#w|zH4_X$uaJzssWRUgY8kgK2g?7hci zb}+R3aVftp-NQOyHVjMHlExK39{vHN!{-wprJ#b)6nH)+RPqM z@BipJ)VB0|Tbh-2=uf-1Q{0W*Ljsu*^Qs>d!oyh6s#;UIZJ>QKAvF(sG+YgX_$GjN zIfIiV@of++`h5F~ zq-`IBGJyPtl{G>>kfatJHmU+YR0Pr&jNbpEU2<>_?t4wa_;d+*(AuVuyvavMQ(Jiw z=`%Ip9j@fsl_3YPoAB`U0eM3&!YN8aU6_;eFna}1V`Cc8J)=@WR{1`2cI$pMuAD@z z9Rj`7z)kutt;jvR#R1CK=VsxD&@5%|cq}@!paqcxY)Uq0mI^i~kpVEnthh_9@{<_+$f3ZiN3YeDilqpQgX7_~W$p!yh#po64pdI=WcgL)^? zZAD@Pf+Z$6n^yruOSeoTSlh8UAI{*Pj-BS)Cf)vXP6QAYrG@0T65Be%6-pf~hV^-{ zW0hP=^z)txq+6AwN>#Z9I|3AFMg;|jQ4ky2z=${z*l6{Fj^G%^!kdAEzPvLNQq@`I zonUa22Ap5B%wF$`yw%=-=z(ZfTyu^wv)rRAnEt!|XdYF>zUCU#NayNJHy4WrLhwHF zqeoo|(xO{~euIKKGhEz*|Txt5yciqs17gfEp>Amb_%uDcdMa9AGHlT3el7Ki5AG(td11 zq@z`2ns9vMIS2w){RXuZMIc6MgGs1aGtR^kI6&%9n~wT6j&%)j|5TP8_#Grdv^IqBVsWx=oDn7!@|wjq*awKC zB-o$O;Ch?1IXBtV(JQSiN6Vfts=R_`Cj1PAHL^Px*3YwJ%@(fYY@4kS_30=+Bh#SC zxL`g`>q;B=)uw*!7zHtq>yj}5z3YZ(_HW&=B|^p{4+9Nz>ughfES>2JTBx-v853X@ zu;qPYoqOMI9!?U{#61coy8n{xwW^vJh*CLS-f*)~JkW`@`5q`0<6U|n&WhM^A`Ex@ z9`2KN4xEEiTu7fkt3WGzfh zlfmoP43IsOQ}0opO}si>fKTkwR4rpC&Cg5xg&-bkYLz+ZmH=o@KOpDC!jLp(622 zM&A%N^^0&t^O;){5c*$`M#jIu-USSPXy2CD=gC>dMTFD7u9qe{m@Zwd{12@<5vU<~ z@8(45ueZpaQkk~AtfsWQD?HC*@PpVOO}zMb-w^tOJr9hn8M+LGkUbqc7Oy7CMm%D| z2eL;~Pw08m$N?2Z4b;Z}pf^lB)Qq7Y-yFaNQcJ9kXCHwnqlSX}NHb?JLnF>BG?;i( zrZkgkg))Nx7J(@2gq?kArT-}2!am6iv<5_lOI}JJMk#d7BFu0T&P+{W7LjKLHvgiq}CI=7D zr-%OtfeubIwq>iC0b#Hdf?FUT3}Qo$&_S2*!#$lPw!p6Z z_dk5sHatGX%V1S%mAxFAx4ObqM|iLtV3M9c&c$B^NsSQ_1#^SHroX>myWekMs6TZks`4+~6hkj_W>tJ!L@VA-Gpw^&O!Hgq^|Fe=Xe0w>}^ z%KeqO5AQNb$J%q6xY+)mUI6*Cei$9MC76BxaR{C=+JR3 z=pKKkpu+CwRpeybITz~E*)s4ewOK=&@^p4kLH3AK>TEj0k}>m+C+K^m$`hWQa^E_V z3)#U#I(&|d6X*Da4`1%UuJ09th1T;%`>}o0D?zW6HyqV^bdBz932_5Sw3@`W_m4b! zz=^IMj_JLGIzKO8yUJ4?eTUHdYAVDcASYK=>;NQehl<@m_-~veJf$yo$R3yf9w$@3}9SSUl?Ys ziN)B&6Jj+w{9)G2@2ImrrO?Yh5)ugOo&LZ<$1!=6`>-0yea42p`(y>NSjXzjfIO(y zO1Zoa0&!myWsNycew3hoEb}<+GIThC)U~@2xmPA+Qag3oASwOBK^dJ40sPO?c9BjO zZPr_D$CJZvf{CKOw|ESdS!Mkp@>4k*F0!_eCFAM!{_IPK{fFm@HRf!YIeF958}-RI zBh#u1EU%W;Oh$?^iKo?aQFX$J13E!qHNS=(V{LX)J&p)G@K3wyiE(G)@A6BaN0s_U z?PAy9Z!qssSo-PAttJK$@X#^ER7Fv`=uQ0&jaeh}rhD;{xW&r4Kk~Zvc?{GLEAI^X z%rqB!@%5ln%^EHqM~L}Cz$F2D3; zZU&A>(Ri&RROWa{EHj!P=4z6kwPc&+j=$Jhq{)3W2OMY{Kqja>@VeVa&ny~{#M@-# z?maoSmF%fGvI%~)zekoLN{ z2kq%;HkjGm3otC16(99h zmII_EJy7!C?@l5@>46CAYEL!}%%IDagJq}kDLtzleQLTo_%!n{-Tx2lMbq%wirRr1 zrWVrmsxVXAf~J7U*|4q$#3X#o;}5h>QGX53t2kQ{2Klf_(w>*`zwcgLgY@$+ZYO2r z`{P+6g&)Bk8dOmd^JO1{@u(Co0c>=4aDRS8XS}Mjcx}|Hack|R^mw?}@JB|HSj~JQ z7$kJL^j?UouTF{#f|!;7(loVC?dyy>w`(pPy}_}~?v}(yIk)J~6{#^D`pEoWsYkpe zcxFkPod4WwE?0|s=P0~{OtLGKU94fQwZHxlQ#gG#i zb4r2J(kym~d{iG$@?8?EoR9^TR{<+yRp3&Q5s!ne4f0Tj9t%0`WoJT>2Ih&o`e?dT?IMg4tf_wwYRYP zB2lcevI5RPMz2!aN;@&xM>A2h_vnI(225)&&88<3tir+lnKcKY?94aV%4run(c->c zDms?NRm7=qQcN9Ow1sSc+^Yt&7lWO3XPpd{h!*QjRb_vxFC4%VNT$e-u@=ris6nqn zH(Nt^@YFT4Mz5YL*PUorOF)j+4O7l?)>#6*KwL_jJMIhpO`Nd8X0;6$iaCRJ`pkrk zPbdqqJX>SntMHT(l*2O`^D6kLC#KrgCE+|ma}@zcscE!T(W0j2`=eB~(!xl_nz!v1 zRE2l~l)@&2Q}h7f2&@cEfP-g_7@p2tBUsR(_XpV3y6v zz38XJ&!&82A@ag^T{+BEPf z4UC)2h-=mzW<&&VT>dI61$Mi>VI@|@4ua>6c;L!(RfEh^P(p8(Ma~$lwYUi)6;@`9 zDl7LCZ9dHzmiu2FDz0Y`b7VC@adeb;1)a!QW+B*kM?LuN#$Io4JK!U3_;bZgfST8b|^8t-%0 zaGRi!6!?mD(1K{8)Csx#xxoMU&R7aHk%UjYGTIjq_;y`~_PVQU5k+yuukurMg{T%H zD-=zBErukW7bOMJteRRV&!n+Lkl^&yj~{U>F!2>ltK>$g@_g zNs%3fZ%6Ii2c0>5k_JZcR{&Ix_i8XAbx=z=+P9_8O@*QC*3bRXh3^|Wl~2dDc4_6{ zau@iSP@xT>%s;5Zvs0+(_qwo`_s)T0SC1%H*|_m{Ga#OoD!%xWD*|RC}|Q$og$Bz zcYpj-?9szK+w_-8#3PnhGR#)%SGI98 z^t@=klh)=Ih>{j~!`JD-hPnSp>&^BQ*~f8KSc-!hTZArVQ2ogCE+>U^4H6&wdl1BW zcun1~Ww+6xzP$=b(0ylju5sIqjY&hw0{N*l+hRDUO(wEjiEMavIT%A~Y|uAaT6%=M zR5vM@_%{9#$GNN=Y|J%`b;c-Us=%7{r?=+m9}7+io}uo6pLCpuo{TV9FDQCt8Tk6x zs?S<4!C&AZ=|25MRph#gw>!_VVJdHsx6WUPIulA9ALFPXdSDr?t~nJcHg>wX}-ik}}&WACp$uaQ42ayz8)R5tE}g zdO{jhTh*nVlIV}p-m6wR6A@UMm0VvAO?{+Ot*;qxUFJgSA^OuFETB<518jU_uCEF( zh-p(0tj=u7E*JIG_;9-d5q!sU3|jF+p}8Zr$@c4&B#6J+Lgj${ z%u#LgbwEq$2u78{I+Ig(fPu!lLK8fq*uJ>8`8{i#z+iVnpGJ*D4*KQJS604OG@68% zK{P*xK5ID*87}n`dHlDmj}RfzwHXz*cdjM2#Rpw$?t)ZwcoxEWH)&!5mxVc%ZEX7_ zj}6)inOBp_O>ccE;4Zdtu+ zpH=8?;lz>hGga@8j6o1Lzt9fSKu-OJ6{b;PIp*T#MW5DTr|uXSglKkSlwezyDZ@9~ zXTvN2-IP!xPE)oybH@ajwEm+S#b1114JmP>wJF**xc%L7-}VP{wz$b!j9LEI=OK3V zWMj(ePeJjAap8)k`^L)bQoHlo6eG1R+aQl4vp*;rVotzuuTe(?{Z=eZ0L*QkVkfV{ zJ$l#gMM%EKsePteCw<}w*b4D)2MMeVx`K9R$@)b!NUW&`ZAad#go5U*No08+QowN5 zOz~`Csxv`A+BQ{VP5Ip-$C8}*h1g#7xABPjP`TVziZvG=SH_h#L!elHMKogoQwpTV za;*V4Tv*>Kp~!sH<=ysg3i1CmxMrbZUuhz9faIt&5ZG3%HL5*pn=IjkY=p} zF~ldjMtIQQ#WhCL7pOHC2OKl&HG=S9%`BO*nf=nf)uhBFlnxZ{?ij_E!sF&Rx7vZF4&RpD>u2)t)fRJ%spaj8MA6&Rs@PH1V@(vR#%{(?8T zTz$6@WfgtdT!xlQHci_@tNt|D%Vlo$9)+w&pMZ*Nm91o|@r`0_BO&P-4@kKfu=pgl z7Dl~j59wuqXaW zlp4;@)%TESv}?WF-N^h9LuR5Fc)#$vX7_y3>l}l!!KSp69KBCLIMh4z7#Y%Yd##I}&iiY>+zf8udpfaPjM8^loalRPj>!?oB{p1QKZYZP zq+aOyPhH30+h1Q%q(ex95N5myQ-K&E`6KEy3-w5`Yguqu_m@vJi32*efuoABY}oae zMRott%EtxqC$l!*c?g=Pk&T+$v(UNyrDZX6MIVs=aoB?Y+^$ShsXKCZZm&}9iR4!{R%5KB5uNn=Q!$~$UE8w5`?B-$eBO{%Lm zYC~~*y0JZA;T&iPlXHb%V`>|Q1+gLY?jGaYzSxKeM(d8_Y&@fzzHX^M2(MOE9;}9f z_0eiD^?ybjD{LR*QgEoacHynOAeaOb1VQ(wT z=kzs4??p7M=WPL|u(6)84A4A_F^C{DMe?$S9Uhb?jmX;7n(_S1@Pn!6`@Y4CUdOL^1&{ekIM`J&>I5SC zjJE{NmfL7HM06Ldm%PqKmK|YCZv?}aQXX6)W+kP!-}bt|O^gR3_q+G7pNC_@OJfO# z+|qEw)CdT?bFN9k-jd}~bxs&XD4Bt0Mj|LjaWg=jp4E)mYOjKDtiRjaJ{xXh(mJ<1 z^k&kCyUN3nv+J489K45;N_oguncx(A%Z{QpjLva;T9gZy;dynTHpw&al+9F6Bs58HRqj+icCr-T0|vg1 zS)q-&{Y0*~^LR4J+d`Miji=0>irP80BmSiNL_gU(olxIOdH#*>ceW9{xr1TkCdAccWy0xj4qwYLz>yUV1n={1S~Lap5fB=AvfIN zJpu#@9aQUoK|lhj>t^KsX-~&ZMU5-6_hvqC`j!q=+O9Mamv%u8cuVY^BUT5^96$J7 zhxW%6i=j5RCLvViH?@x9OF52G+)X;Q!1ehOls%CzKNLE5bUT@IjPc<#auq{AA90qFJQglABk> z&{9?HT{56YgMxH&F z2*G79z8!lNF{fL=x6^AY6BW7{GMrqEO%!g|V7flUl~hcEXdR3kQh0m9V#G9A^c2V^x-eIe1Y+gPq-t=} z7eYqp>(f81)b|j)*%1_hYn<5N8hehPFq?OCi2!WH>S&4LooP;kz^xYTUF^X2iC4$H z>6ndxee`Y)FeeB0mdq{~*ep#cqOKq^8++}Zz+1e;A%d2KT8LTO0t4UfhPcm@mJX+* z!_c^Z+Jj0w-kYAGWZ-BL5*s{H1|aI2@vwU2dM}INVSZbePb3w@@(%X2g~HC9@c*_} z+(l|Ecwm=_r`hMhFHtiS62M|nSoH5@Iy&OhG=*d+W<=x`WOH^-4q+@2Tdhzr<{67c zuT8!&Q{>RiWaRk^M12>}*=lZ8nD_9c!KBEP^o=qetg3R_ zVx4Ro25~%|L|NEmJuh1n+XIOus(HIyoxNR#>UL<_z9 zHlbk?zFHH8NlOk0R}rll-8zzJRD}tZCV#q85Tj~A=fA{C1h=!ATcqe+mdiKfjeMIq zyNU9QUwsH3LK_{O5`VzlLe`F2^fz1uQBM*AsM6b_>eSJX!A#=lo&djp-bd#eA4T3* zm!uG#e|ONjzCwD8jKT5vPaBcxJwxI(!xu~%rJdy<)XUs#SvRZkYAdBj2AmkVb%U$$ zEiP;F)n-ZN(iG(3;dFHJE?a_-iu($ut}MgFx^Af!4Gc&p7|mErljEyuc%>CELg>dY z;=hH|dVW#)RT>aAXXZn0@E*!1*m>Pc#C8if_0|!MzH1~;u4Nkxn{=RxC6$sAVp?C!wn@uGSaNh~`zLkg2x&AI{dj})f}fXsQ_ zZ&dY3)0AS35keggzqXXGMGi<#j_^<}HYjh_yPAg<32>-Oj+dgq zf0ZH4eIW8e?ekF^5)kjv$cHhw*d{CN=*5v6wzX#k%frEUMtIL&CRoY~lWM$clC0Gv z-NIJs2n{BrwkmdnyJdU(7`}1agAra<=U}+@m+*d(&{ zNg|Q%)#8b*$IrqyPAFJ4Bsi^&{cMf1pM3{ad#mb*AqL=3O~3wZb4|Z2`wCgDoo{Iu ze(y2D#LF0Tw+;X|K*+yweHakH2Z1ME2)d|922r9jS$xZqTS^Vy6&ja8wu})=LZ;kp z?y&Ye8px)wUvDgeRI*;2y-4qZ5B86naQzsO&4$0q1A{+TV_8BY-7-dW7UXRbeggF(c2N3km*0mha5W`ywgnq0iHY7z@2VXeIDN)9d zf0bsjv*+E(l^N&q=UqSzBbhwBrXcG>rezRLY7K5n<&Zd1KPtbLCE$x^VC|~J}nYb-=;w|J-&am*RR^?{bu`LJ^q7A*z5Nf}# z20Z4r-#eoH$t|1m{{0s(NBi89f}k7>LO(wn56!XZI!Gq>!&;pZ_o`vedWLDotI`ZzjxBR`#XccZ%5c}X2TpqCD z497AvTD&B@GH>#(%OFdG{~uRC{c=EZCH>Vb4PmdT1u4pp^q$H28E2C=P>vS?L|`!$jU3|`z*Ib}1Ytp}nxP{z7VT~QIpyZSkc zX6&~iJs(1300c}|V*&kc8t@8dH{F2qPG8I^Ry{-AaQf+KQ_%Lq%U=&H z%kfXUYGlM$f(M_Rrp|;IYKod zW{;u`X@P09XI5!o(NO$mWg81#qS7)r9=jhx>2le@4>Tr?+=J~P`=cv^@1nZBK=5~F zYu}AnaIs!e_b)3{^otI;tuXtKvP9Vtd#o%p%exk@OPwSkOxrFAh(uwS_pu*@-=gb? zEP9W++H=X?IY->pUt?Q2{yiX7Ia`76=kYvpGe*xW#7ez|neS-_0}2M{H8t$!`APYawXFuP}k&t{tC#dpj^~?7{T*tUi5( zh1B(gISIT4_fn{p{GVjvO&%#RiPwmU#eYe|2Dd#=Du&@Uz4LLp`X-lWohLGLEKV;z&LAQvxYu2vzIGp$-P_$zyi%`gfr zf@eb5hiF7@Hgzgeo=}-yEzExEWS*w4N&kol)ngj%39+5HR;r+DgQ&RF2jtv7H$+6D zr=*NBh9O*M751wF6j~Z%F=oDwg!jJa5i3x|0xC|B{Y`SiO0eO~?AZ>CsrZ}6P{Y)J z%sKf=C9C3k=1M#Ls(5!53 z!M+ndProqDbDUJn^QDTjg`#ZGXiL>j(`eHMc=JwSC`FP*EnjJTN*b1@PfOB7%my6+ z!NKdW$or59j`+1FV&-#pC{{$|8tsxtJMC)@)$Z@!PVHn*e!%E#Y{Zopg!&*`E75H6 z78O)v*sWr`7pkZ(_Up&^P01gBj=08Ij4h}bfl`M8p>0Er$~7y$xF^;ypf|-^@S9dcGf0^+ zUNHz(U&`Y4LVA5JuKklaG_v9vk_}O|J3^@2uQo03QkZ$H~fgBk8nE#*s zysaU_v@}$-4!|yy|JuI0FB8dnFP`Q+G3dv;?rIx2*RIZyFJWcHh8c$89O7!=bJyI` z3Hpt)7tD0qLlROkac39FmS?B|YBOIkU}_;Hmt7Ej%aWEF*s2tsl=8=l(kSqZfKzgj zT978@Ok2{~(Qw-y`rlf%&8^Bg9E{F#sSckr(2T2m4&kCWLAey}rz91qz#%5I=bx*(eo6ulcglUr#R|8eypKfrXe>&0dU1^38q+^GZ6~1pQwgj#*7$}?M z0P5{=hwK$oPvS>6lgC*K?zJHGSf+j&NYZ`!l|%dL=y_`5E>{a+HOyF4s<$VY<-`Y) z={da{3XA8Q;B-|f@CzYE)+UY-zP!P;Ne+~l8wNZFM?AB1lUf%#pwtl=oLO^MM;&m1q)6dBts+%CYG~7sEdkm_^qb47AWh|Bou5h==G_W#^|0`+1{7E}^fQ16dHq`2{+U?l6vJ54xqB)xP6Wv5iXPmAVBS7Gga z#1%Dc@0>~fhU;IJLx7ShUWdw!O35Z7o#DR8YkBF%^&#l{*=ZC&PX z3as&0xc#+VlwTv*9xs}6vj~Oay-H=GPHx_pW=0E8hxv1dH+2ThGnjs3Re~g-(W39R z$4ycGbTRQHFK^^fiWlDGeAQnC7A}JzaCWb0$avSntn*#TltuQ@|J7qj@9bx zN>BrTUf~pTy;X^FV1y`+wG^ZuS@j(ZlUI$pcjx^^D+RvX#Drpee&+S9E1O&wNNK;P zJSmCi+gN5?H%q*e*!w#ua-_;-zsTPfqg`UxXlVH+nv>T?J%kk`XPlk-=1>DJVSgDM zLemjnyTpuYIp$o*KTIg?m4pW7Kk~`iD{T^(%(TXW48x_u_Db=ab0uSH%SJ)>kD^CF z6WVqS%)GpRouNVQKySP=x!6rTW=9SvFWP%ufwTHeKPNxEL#zWSKz2cWBEuC-PZa<9 z${<_J4bfK(D*EB#W$O)#IOne7-w!U!8UPvm=DShkC=3e*ENaXyytJ}Q`@cyB$G&E9=&nD z?(sJkHAAxdgu?TiccG)~qt?C1F_aKY;qt9=)#0C0P$fTN+V&oznYQdmQYz|mTfzxf z2tmg;a#VNrE9~oa50_n@Pi)qrQ&^7zito4zN5E=<(RnR?KHw=I0jdW@(yqbBzXA&QW_ay3S%9>;l)=;L-St>0(-{_jjB_#l=HeueoTdinzC| zXBNKB!B6#yb-5`vf9)RyVJzZGZbrd6!K4${xuSj5knW@QND2mEzR#~#bd$C2vFR#Y zrkBbl$~Jc6(Yy^`L(QM_~c z=$TLz=px-!?5!n*8uuYW0(<;x&J?V3-OZ%3o3eKGN8SZUlPKe>6$te2Z^gj4Ku1(M zV2E;5aXC^DdvI$zrN3`IYglu&@Z_8UHvZB3aFSMpZVLUekr38k*uj)=35*#>0NUJe z^E}(u%1ceZZM0Z1MxaAF*yF$hziCVbaLO4Ip+Pv(-f&$1Bh_MzkawrQRnl0r=bIOI z;+pqrv_0WqCsKtnwosy2mJ#MvYP}OZ9>KnTFEj<9wfAFjT`!R zH-SJcL4x8W$a6aGlq^h(7lcB?Cb2FMO+afWteYn(@4z>Ar7e*5Q=<{icexs;t~WJC zBDP9kUYf`7e9x)E*Ot-rYS$r+**kxcO#d;=STz*~@%Ajt>;lO|z%!~YNtVY%EBSLi z+Iy9fVG*D);Z;s&&?VKoAJD~JWsRe;kCxwjzaPYkJHuv+w%TOhyv8<45_3zG6CBEU z%rA@17l}>bvcc#4!uH%9E-5k(edynRw7@Kl&p;M47{5-NatXAZiMu(vVR^#8WUE1= zh^*J1DkZbq(FwXM7+jnm4cb1evYh?baq~iA{{k{kPTb?K8Z=tYv)_3c?|uWwAc=L+ zp>(O^?2$D7^aVHx`L#Vn9Hur1!ab}N7%jfjkLdtSXcN}&9Ag6kATXPH?Ot;UKFK}D zD=r}-1MJy+@3gtv)-E+!w|GD%El0o18_+IOM9T|1#(7fl|7NoprH-3tpR!{;JyEt~^*3;TfGxEJmACS-!)Rl@|pBaa0RQSW&!o&MeDE zl!U|b)|hMm1a&UQXQ;p+uGCiitFLecKMEQ;J{l(cktoFY?RWZNYOn}YbiFH6Yo(IzC*-`pr zNzl96#e{3mx3XB#zRAD|RF&qDiapqgu`-5eI*+@H0c@<}-!s-b%Mm@0)qvZ;T>xp?X1Y@}ve9?;PL=l`?Y+p=2k2?#6Unds))S zc~YtnyAQjMTIxM$)U*X8c`5HhO|x&}b@~u0Tqz5_iv6(xW%H=GNhk|wd;2o13EHRm z5p5iv=T^KhZpohpD4ZN*|7rzzpNZkDJKb`=EMh*4(UM)i-!ueq}$I-1j#TDY?R`UMR z)sw!v@0nSjVoZ1ixD+AW;QKM>Y9>~1o#QfCZ_G^ z`U%oX5D5^-kzehXxZTpxcOG28IhynbH+wM?P&1!`DRJzvb1Q1m_Ye)+>qi@lq7JDE ztfha8-#~Fm(jrZzabJ&o^HEHn1-FETSM|ZgbOBqKt+N97&@YQqo)8^WU3BRzsO1Q- zFJRAWC>U4Qz#36(<7IJU_cTE!yMUdGxQ8W-CZ4XF#G(t25sn&aXs4C%gkB1l<0mlz z3!PYgZLWIs|C14Ve#>7wz@|b5N{M8~dtL&=$e|1jM7Oe^ThHB`Af#AZh$CF93v~Z1 zQaUXOpGaH*OJvSBbVuO3;WWKryIJj& z?iCDW=*Hs!p2G*ut?9t&BFDNB9~AkpZKOn@XbsE!NxK&|55n`kKX;>=$Ok2$oLJ!% zgUq62*BqVM2?7Maq3|+p9#UI`xKO|aD~D5UjJ7lTS-Gk+4Oiy6h`38lHFUazGX=K5 z6P<`l#Y-wSD)wfX%c;s*l8R*{jOv!g*)fG%W`_9@ovfK(nM^~rsW0xjo*U=MAn}`4 zz=nh}gLZm0;4l`m0YE^HjV5@isEZY(;GmN@^a+Q^`v>)poixvbbL&yq%kY3%R&m{j zEj@`J20d6xh!J`~1)&P8@Sa@GF9=}5XqWaP^a;i_?T6DzY;W@oK&!_kTO-_&07-X{ zqi)6iryt6XXvw@qK)fmBT{RoH<2`TCRaJm$O}47r9+!)mA!VvZ&nXFq<*hK+{s`(_ zj?Xo7ebCbwx;?u(xDVr3o%E zo;~2C+jI*Aa1g+$bM{T>ma0Km-1*K{>bXJmivduoh%1kS^=zX|P>{=wUxxd-obUH4 z)Z|*a1LEEY?9hbzdHt9{%P~LqDI2o6M%H48C_!;mYO77bLo3e>#yPD7TO|xWXN;Ar zT(bNST5M?QLv9=oR1YE_h9d-*NZtjer`$Z*lYjKN-h`C69r& zU`~y>`(;2DA{klqGp(?9f_%OBiMdc z7Dz_&eK|6iYc2KmKKp&^z-BAK))SR|fSk5l$dYxNq#nms$Ju7 zh3Vv5m*r~rsx0Ff3g&F5-^kASweNgfcxkQ@gZ>`2B_2NgylfyUgS@pTJO-Tgz8m{DSeWjpMrDDnF zk;~5M{7=-99jfk@f5nb6x&8^}@GJmNMQ=iW@k)LB{cX;Sz-+8p&%st4G7Dy`WzQ>ms5(RzvCp4f} z>12FaWJb(Prmm;ZGC2d*MNLZa$=Alx>(+Jao40x}AoAe$SqceGi{GqpCU1MPzjikQ zfL`UR(tQr(>PbuWWLW6xHOWWw&Q8wIm2}@h4Mszs#8C_zSs!|@z0<7`HL}(6lqfNx zz(P)12a-S~x<>Het!qC;W#Q}(mBV7sgjM?pf19qUzC%B6ewVDdyHsNAV&pCS9EMgB|&Zhz8G6 zYJodJ5qOY8!Ow#5@Bm!uZEWSVNoDs<3=6%kaVhNXpWn?=YmG;nEY8L^06GR`E-&i8KH0w z&M39H)!+(R(^}NzTI4>sREWA5MGAe9s&2Eg#@K7L5px4+&mj`_0=Cc`(4tR`wuPeL zWf2YGA1QHWoFKnBWVX3#!o(SPXOUbET@_XCq4mHfOnOJeD-%cVi@A$;bg^CZP@;Wf z!vaQ+K#kS;tWGACFIU;u>s8M28U+eXY7(4>_%p_K2XNRt8~XC#rzbt`B`q^7t%ULh zV<*(T!>nJ&{HQ@yM89o0Z`2GssY)!W8WPQ3sTZCV@e;6%vh-rk4(!6rF zFZzqzx@75pupAxrb55ce*QcE7cQtcKI_HI_N_N+`%sUqu872`CpgdmIC};H9%kbxI zQnYo{BN}>Eb0E%y|tTb z9kw558VN>wE<9FD`B)!?TGKe5Y89?R0=doTBOi~7-tj*}K{sArIt*F#e4$Br^D54Y zVZ9_JFIUIL=mjmIeler>c$wV7V%-*3dG^ypTB@9=^?dHIHd>-#w)-5d^=F>qf!E;b zRTKH$VFg7P-rvlFfH=bmbB<77hOM?`SwCm~0;g2Z z`bEavuE%+fIp6ECh!~;j)pIPHMC@MnW zs@?yd?|i~Q&n~CDpV5Nz=xC_d`wVEq4DF*wK$Shcg-qvvcV5aQ?$puwJ}9X#Hneo) zI+b$oFd=KrAk6`;yDD#E}K1|w>D7+Om_`KfjktPZaasCu*ck<=)Nn~ zmx6;xx^K_(c&Z(At#500rwl+2tWZ^qVo*pXG%qxdCaQg0N*OKI?+L-esMCocZb|Ug zFxH_b{X%$|;upht(Xx`+S(RSWEi2sY7>UY&$NIj@#=1l=M7W-yvX@h6o+Bojf6Hhk$1RY3 zlCP9+TnRc5HH7+nNi++sJGVJM9bKvfy^T21(2ZzpF&3(HUc?fOjDu=NPCSA`@ zZhrEsDX{X|$$&{s7j zgr=aR6$&Q*MmjU<8Y55b1~k5%^o{HdWPDKAtff#sOk#ch{^te+MSJ_4T45P>)i9FP zg@&S9u(1GwjG}$w`DSqIt}hnwSPJlSq8I%BIkzt5G^T~h>*38Lil%&iW%tM;P!S1~ zjWX>mr-LAlidC-+P5of*6095<2_JnQX+03e#h3Pl?JYfkd>AM8jb5j0Imn!Uuhn91czT)3K4-mAkwCHnjBFNZ0T2xy0%7;!Fcdn5Kuy%5uZ>S(2Oh zgTWX4WV?wlC)F|QkcYy%;nOF*rY4x3>H0R9P2a3jz$$2;q6pjixtV1VaxzmvBDbe? zQ`8NYzan>qiYu+sG1`m5=JfxdZobnJ3ZBhJP zT8XV&%Xr|O#I@5b1)Sl+uC1udJvkThh?*?z(3)DL)tY%i*klHz376&?MwH}|>0K{u8 zsN+>|@~UUjzIX9C+sbR3n1ykvWBJ(;-e`d<(*A`E@}cGYInFNbniHAL#Uu!KVKiutwP6gUOx#l~PdJEO!Z3 zd(aF-&TBNk-pAFy-vo{=7GzXkpU>v7^MerO-TZtZMC?c*C@Za!&=M%1s8KiiAa-5> z+3f?_CsvHFF8z~#N`pkUnU1)^X0}vgeJ-G~B#+4aMWvmzgvOg}44!o?%{_M25Z}HJ z4%CqRSkeLd9>2dKSj&2|QFO4>h@U4>W~xhJNa@_F4c>|6;&XR8c<+X;4k}WM>qJ=l zPngI=7AA85fw z@l9f)GMx#7IYP~aP08e6cYPQgC;x~L*6tbO*@VP3h%f>_eWecc4!u}$zo?W!5e-qU zI}mmtby;0i(O$!!lr^OG^`pfb-wD@~_7H3ILm-h6~JO-Y2utQwg$eRY7dt*!)ipss5aoZUEmko*?NrX8!Kwm;-B+KwdD zw^X(vVs_%plv0Kk26q*eyeyViA$V|rs0|hrEmLZG`z|_`OvRzMd{ocfWeC31eBjk} zeQwgmM!x(IvJ`J4B;$-^V-^T?{?aIKGsrv4b!Ci8WsWo}icg1Zk?DG}U<=8bf@2EEdblR?-ozUbm!E$+YM)v}&0$ zTGF0%WT06zImySgBWS?TF>V)}R((N_?-1xJ*;WV&*iRd4NhCh$n;Q*v`B&mM(C=jP z9Qr&M%~iUZHa!*l={1AnQ`a-FuwijB@8u+cIBlROX?nesAr2~Q8bu~ClN*yq5{mJ+ z^SEUFX~E~~lFWawdxFqVO^N*GHsj4qkK4IW#3^PTLy*yEDtjJMQOj?F;#{SfdJ%0c ziT#TQAcmSriaxV~G^Rk)xc4vfJp=f2Nr5@K580W!tZADGW`34}+I#|+UMcu4Y%c7Q zPyl5IDwRhOdxe0}KE}>RXnCG(JD1D46ajo>T%%Z?34&02*HbiEI*U{87<6 zW|M%9mPao9n{P4>gt}>wEA8CymTP{5iEvM8EFere`^|%}ri8b@Xgm=JOP<%csoDAq z4RW4drYt*vZzzXi=ANBKusnJ{tQJ3(HhfFfa$b7ll1-t1=f%|Qgn3WztnvzUohZRvc9yfwsyzlfi>ZCq* zSRvWEpM|{s4~#XjK+&YDq{0`xQ(Gw=rVha|WV>kz40pJsK>)~2#vD!guGK{x17dQS z(oUHz#(wk0m_vGTBd{`IOFhQ&Sb~95Cs20t*k~t*De-VMBcp z;-^kx1-!1)9I9oUSD9!+?j`bk=45!hMF6=z#`k)(UX*tNDas!J7R``h?2y0xnGfu| zXrEsZRx>xpTsx8oj=M}rq~IQ()B9@O+lEuYGyV=`@-^JdPtf{@jH2p3KiX};kCi*q ziG;eF|E22ZMExwEm0FBo6_a0@e0Ft#DTS7YJ*^(z&xdBn6~tLdwV=zN;3H*14@nQR zxn+=g2^PPu>%%5;%!P$k9@^@l|Br|2;4p@XWUU58c?w~b!bBvac^*DdXzTsw?VV_S z^G{7ELx!GG!HSPO%=#C{W|4qe_hH`Nj&!qE(ptL0gM)G8K!Z!_0owP~Ud50&K-L|{ zw0I`vTB=drdIYAmlZw&Bz*}JjaIk5519{C{d|+g2%wqdA+>#>1tn=LkZIaWx3V=^l zG&!g-44v+kz&Bif%+*&dpqx4y3NLBu!%x1)`85MBK7;NR-06c;IX$C$xD~69W-_TB zDa(%#nh))WB^731O>WjuWZjGn3Dsj(v_rf(>&c+=q5zXZAi+HHy#emss^9zk`N!G7 zX)?kJOtms5{Vk3*MOXAQJ|0;pC`5{9x>CL4oC|?lqA$wKLu)x$yigU9H)SSbjXpVb z`w*i}KOJu((sxEF%7@Htm_IaEan;~-S2cewjHDkdvUnbSYx`#V(RZFPmZ`@+%*6=` zeV&|)HPfmp&iKn`uD-8in37G8&#vJ0&_PJoBlL@slK+k^hasb`wq^1!PsDUvK$=T_ zLqK|yf#wLt=K}u}4)3LMY&U}-CflM-V>`A=hC!FQ5@<3vnpQVOw9ytoa6fcj-AH4Z z@3E~IQ%0Cp5d!Em+YMKDKyTcZ5NA9Wm3zL=rp@nr%AnWsY$#HYVZ*;3Vzz(|=dk-* za~XEP@aY;ZRGYLndMahc>X__fp;IX?O{DPi^D#Uq+@|(P@cnP{q&sj|h(mznv`al& zbA*+zfg*z@VuTbyCMsox$xm?qUc7ql6Qg?w=3+{>_I&AFO3^5fUWPkj=o$gd_amtE zVeS#^FaO<9)g>%d3R`pws6&>7!lk|A`;Sy`(;#*$9^dAds zESbwNkBkTA!~U)c1`3_dPYc%diI(L4vj4FS`FO13KiMOO?=zo~h>lxuE&bo^th`ebhrnrvQc0)lON)9L# z7fUjETQQWTIC|M+SS#gY;WgkWf(_!gLF#uiEhYnwwNZ$Bt#jKX9E1Mpj7-w!5Jk@F zT%V+c>@=;&51Q;g&U5%Fm%F6#eNGJ{6iS%pv@pC7tMPKNz7v6g@Ir9FJ>IrSM?M(a zd;%ISd>A;fAlL_O^OweSr+2_vY(wnJjN=#;_K6_}pCt

&%>vj$!G{DB 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 WS_gRE&AcLt9s)P!ams}b$B+Qa^WrN2 literal 0 HcmV?d00001 diff --git a/dotnet/02-working-with-your-data-safely.webp b/dotnet/02-working-with-your-data-safely.webp new file mode 100644 index 0000000000000000000000000000000000000000..2ab7edcb39d10f90025b96200279f11370d73218 GIT binary patch literal 32908 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 Mu_T{B5ajnj0B`Yqy#N3J literal 0 HcmV?d00001 diff --git a/dotnet/agent-framework-dotnet.slnx b/dotnet/agent-framework-dotnet.slnx index 3be35c1cda0..06724902f6c 100644 --- a/dotnet/agent-framework-dotnet.slnx +++ b/dotnet/agent-framework-dotnet.slnx @@ -121,6 +121,7 @@ + diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Claw_Step03_ScalingCapabilities.csproj b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Claw_Step03_ScalingCapabilities.csproj new file mode 100644 index 00000000000..3b5f9735d9d --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Claw_Step03_ScalingCapabilities.csproj @@ -0,0 +1,31 @@ + + + + Exe + net10.0 + + enable + enable + + + + + + + + + + + + + + + + + + + + + + + diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/FoundrySkills.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/FoundrySkills.cs new file mode 100644 index 00000000000..ff386850f14 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/FoundrySkills.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.Net.Http.Headers; +using Azure.Core; +using ModelContextProtocol.Client; + +namespace ClawSample; + +///

+/// Helpers for wiring centrally-managed Foundry skills into the claw via a Foundry Toolbox +/// MCP endpoint. These are opt-in: skills published to the toolbox are discovered at runtime, so +/// they can be managed and updated without changing or redeploying the agent. +/// +internal static class FoundrySkills +{ + /// + /// Connects to a Foundry Toolbox MCP endpoint and returns a connected . + /// The caller owns the returned client and its HTTP client. + /// + /// The Foundry Toolbox MCP server URL. + /// Credential used to obtain a bearer token for the toolbox. + /// The connected MCP client and the underlying HTTP client; both must be disposed by the caller. + public static async Task<(McpClient McpClient, HttpClient HttpClient)> ConnectAsync( + string toolboxMcpServerUrl, + TokenCredential credential) + { + var httpClient = new HttpClient(new BearerTokenHandler(credential, "https://ai.azure.com/.default") + { + InnerHandler = new HttpClientHandler(), + }); + + McpClient mcpClient = await McpClient.CreateAsync( + new HttpClientTransport( + new HttpClientTransportOptions + { + Endpoint = new Uri(toolboxMcpServerUrl), + Name = "foundry_toolbox", + TransportMode = HttpTransportMode.StreamableHttp, + AdditionalHeaders = new Dictionary + { + ["Foundry-Features"] = "Toolboxes=V1Preview", + }, + }, + httpClient)); + + return (mcpClient, httpClient); + } + + private sealed class BearerTokenHandler(TokenCredential credential, string scope) : DelegatingHandler + { + private readonly TokenRequestContext _tokenContext = new([scope]); + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + AccessToken token = await credential.GetTokenAsync(this._tokenContext, cancellationToken).ConfigureAwait(false); + request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.Token); + return await base.SendAsync(request, cancellationToken).ConfigureAwait(false); + } + } +} diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Program.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Program.cs new file mode 100644 index 00000000000..0e705c83813 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Program.cs @@ -0,0 +1,224 @@ +// Copyright (c) Microsoft. All rights reserved. + +// "Scaling its capabilities" — Post 3 of the "Build your own claw and agent harness with Microsoft +// Agent Framework" series. +// See: https://devblogs.microsoft.com/agent-framework/agent-harness-scaling-its-capabilities. +// +// This sample builds on Post 2's personal finance assistant and makes it *more capable* in four ways: +// 1. Skills — package finance know-how (valuation, risk-scoring) as discoverable SKILL.md +// files the agent loads on demand. Optionally fold in centrally-managed Foundry +// skills from a Foundry Toolbox MCP endpoint (opt-in via FOUNDRY_TOOLBOX_MCP_SERVER_URL). +// 2. Shell — a sandboxed shell, confined to the trade-confirmation vault, that the agent +// uses to reorganize the accumulated confirmation files (year/month, rename, +// archive). Guarded by a deny-list policy and a confined working directory. +// 3. CodeAct — the agent writes and runs Python to crunch portfolio numbers, in a sandboxed +// Hyperlight micro-VM (needs hardware virtualization). +// 4. Background agents — fan out a per-ticker research sub-agent so several tickers are researched +// concurrently, then aggregated. +// +// Special commands (handled by the shared HarnessConsole): +// /todos — Display the current todo list without invoking the agent. +// /mode — Get or set the current agent mode. +// /exit — End the session. + +#pragma warning disable OPENAI001 // Suppress experimental API warnings for Responses API usage. +#pragma warning disable MAAI001 // Suppress experimental API warnings for Agents AI experiments. + +using System.ClientModel.Primitives; +using Azure.AI.Projects; +using Azure.Identity; +using ClawSample; +using Harness.Shared.Console; +using Harness.Shared.Console.OpenAI; +using Harness.Shared.Console.ToolFormatters; +using HyperlightSandbox.Guest.Python; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.Hyperlight; +using Microsoft.Agents.AI.Tools.Shell; +using Microsoft.Extensions.AI; + +var endpoint = Environment.GetEnvironmentVariable("FOUNDRY_PROJECT_ENDPOINT") ?? throw new InvalidOperationException("FOUNDRY_PROJECT_ENDPOINT is not set."); +var deploymentName = Environment.GetEnvironmentVariable("FOUNDRY_MODEL") ?? "gpt-5.4"; + +// The two folders the claw works in: the working folder (portfolio.csv, reports) and the +// trade-confirmation "vault" inside it that the shell will reorganize. +var workingDir = Path.Combine(AppContext.BaseDirectory, "working"); +var vaultDir = Path.Combine(workingDir, "confirmations"); +var skillsDir = Path.Combine(AppContext.BaseDirectory, "skills"); + +// +var instructions = + """ + ## Personal Finance Assistant Instructions + + You are a personal finance and investing assistant. You help the user understand their + portfolio and watchlist, value individual stocks, gauge portfolio risk, research the market, + and keep their records tidy. + + ### Working style + + - The user's holdings live in a file called portfolio.csv. Read it with the file_access tools + before answering questions about their portfolio, and never modify it unless asked. + - You have skills for valuation and risk-scoring. When a question matches a skill, load it and + follow its instructions (read its references, run its scripts) rather than guessing. + - When asked to research several tickers, delegate each one to the background research agent so + they run concurrently, then summarize the findings together. + - The user's trade confirmations accumulate in the working/confirmations folder. When asked to + tidy or reorganize them, use the run_shell tool: inspect the folder first, then move files into + a year/month layout and rename them to YYYY-MM-DD_TICKER_BUY|SELL.txt. Explain your plan before + running commands that change anything. + - To buy or sell, use the place_trade tool. This takes a real action, so the user will be asked + to approve it before it runs — explain what you are about to do first. + + ### Important + + You provide information and analysis only — you are not a licensed financial advisor and you + must not present your output as personalized investment advice. Remind the user to do their own + research before making decisions. + """; +// + +// +// Construct an IChatClient backed by a Microsoft Foundry project (see Post 1 for details). +var credential = new DefaultAzureCredential(); +var projectClient = new AIProjectClient( + new Uri(endpoint), + // WARNING: DefaultAzureCredential is convenient for development but requires careful consideration in production. + // In production, consider using a specific credential (e.g., ManagedIdentityCredential) to avoid + // latency issues, unintended credential probing, and potential security risks from fallback mechanisms. + credential, + new AIProjectClientOptions { RetryPolicy = new ClientRetryPolicy(3) }); + +IChatClient chatClient = projectClient + .GetProjectOpenAIClient() + .GetResponsesClient() + .AsIChatClient(deploymentName); +// + +// +// The harness turns a skills provider on by default (it discovers SKILL.md files from the working +// directory). Here we build our own so we can point it at this sample's skills/ folder and, when +// configured, fold in centrally-managed Foundry skills — all behind one provider. +var skillsBuilder = new AgentSkillsProviderBuilder() + // File-based skills: valuation and risk-scoring. SubprocessScriptRunner runs their Python scripts. + .UseFileSkills([skillsDir], scriptRunner: new SubprocessScriptRunner().RunAsync); + +// Foundry skills (opt-in): discovered live from a Foundry Toolbox MCP endpoint, so they can be +// managed and updated centrally without changing or redeploying this agent. +HttpClient? toolboxHttpClient = null; +ModelContextProtocol.Client.McpClient? toolboxMcpClient = null; +var toolboxUrl = Environment.GetEnvironmentVariable("FOUNDRY_TOOLBOX_MCP_SERVER_URL"); +if (!string.IsNullOrWhiteSpace(toolboxUrl)) +{ + (toolboxMcpClient, toolboxHttpClient) = await FoundrySkills.ConnectAsync(toolboxUrl, credential); + skillsBuilder.UseMcpSkills(toolboxMcpClient); + Console.WriteLine("Foundry skills enabled (Toolbox MCP)."); +} +else +{ + Console.WriteLine("Foundry skills disabled. Set FOUNDRY_TOOLBOX_MCP_SERVER_URL to enable them."); +} + +AgentSkillsProvider skillsProvider = skillsBuilder.Build(); +// + +// +// Background agents: a lean, web-search-only research sub-agent. Passing it to the harness exposes +// the background_agents_* tools so the claw can start several research tasks concurrently and +// collect the results. +AIAgent researchAgent = ResearchAgent.Create(chatClient); +// + +// +// A sandboxed shell, confined to the trade-confirmation vault. ConfineWorkingDirectory re-anchors +// every command to the vault, and the deny-list policy pre-filters obviously destructive commands. +// (Patterns are a UX guardrail, not a security boundary — for hard isolation use DockerShellExecutor.) +await using var shell = new LocalShellExecutor(new LocalShellExecutorOptions +{ + WorkingDirectory = vaultDir, + ConfineWorkingDirectory = true, + Policy = new ShellPolicy(denyList: + [ + @"\brm\s+-rf\b", + @"\bsudo\b", + @":\(\)\s*\{", // fork-bomb shape + @"\bmkfs\b", + @">\s*/dev/sd", + ]), + Timeout = TimeSpan.FromSeconds(15), +}); +// + +// +// CodeAct: a sandboxed Python interpreter the model can write and run code in to crunch numbers. +// It runs on Hyperlight (a micro-VM, so it needs hardware virtualization). The guest module path is +// resolved automatically from the Hyperlight.HyperlightSandbox.Guest.Python NuGet package. +using var codeAct = new HyperlightCodeActProvider(HyperlightCodeActProviderOptions.CreateForWasm(PythonGuestModule.GetModulePath())); +// + +// +// Turn the chat client into a HarnessAgent. On top of Post 2's file access and approvals we add the +// four "scaling" capabilities: skills (our own provider), background agents, a confined shell, and +// CodeAct. +List contextProviders = [skillsProvider, codeAct]; + +AIAgent agent = chatClient.AsHarnessAgent(new HarnessAgentOptions +{ + // File access: portfolio.csv, reports, and the confirmations vault all live under working/. + FileAccessStore = new FileSystemAgentFileStore(workingDir), + // We supply our own skills provider (file + optional Foundry), so turn off the default one. + DisableAgentSkillsProvider = true, + // Fan-out research is delegated to this background agent. + BackgroundAgents = [researchAgent], + // The confined shell, exposed as the approval-gated run_shell tool. + ShellExecutor = shell, + // Keep reading the portfolio frictionless while writes, trades, and shell commands still prompt. + ToolApprovalAgentOptions = new ToolApprovalAgentOptions + { + AutoApprovalRules = [FileAccessProvider.ReadOnlyToolsAutoApprovalRule], + }, + // Start in "execute" mode for quick lookups and actions; switch any time with /mode plan. + AgentModeProviderOptions = new AgentModeProviderOptions { DefaultMode = "execute" }, + // Our skills provider plus CodeAct. + AIContextProviders = contextProviders, + ChatOptions = new ChatOptions + { + Instructions = instructions, + Tools = + [ + StockTools.CreateGetStockPriceTool(), + TradingTools.CreatePlaceTradeTool(), + ], + Reasoning = new() { Effort = ReasoningEffort.Medium }, + }, +}); +// + +try +{ + // + // Run the interactive console session. The default planning observers already include a tool + // approval observer, so the place_trade and run_shell approval prompts are surfaced automatically. + await HarnessConsole.RunAgentAsync( + agent, + userPrompt: "Ask me to value a stock, score your portfolio risk, research some tickers, or tidy your trade confirmations.", + new HarnessConsoleOptions + { + Observers = [ + new OpenAIResponsesWebSearchDisplayObserver(), + new OpenAIResponsesErrorObserver(), + .. HarnessConsoleOptions.BuildObserversWithPlanning( + agent, + planModeName: "plan", + executionModeName: "execute", + toolFormatters: ToolCallFormatter.BuildDefaultToolFormatters())], + CommandHandlers = HarnessConsoleOptions.BuildDefaultCommandHandlers(agent), + }); + // +} +finally +{ + codeAct?.Dispose(); + toolboxMcpClient?.DisposeAsync().AsTask().GetAwaiter().GetResult(); + toolboxHttpClient?.Dispose(); +} diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/README.md b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/README.md new file mode 100644 index 00000000000..8435415dffb --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/README.md @@ -0,0 +1,80 @@ +# Scaling its capabilities (Post 3) — .NET + +The third runnable sample from the [**"Build your own claw and agent harness with Microsoft Agent Framework"** blog](https://devblogs.microsoft.com/agent-framework/build-your-own-claw-and-agent-harness-with-microsoft-agent-framework) +series ([Part 3 — Scaling its capabilities](https://devblogs.microsoft.com/agent-framework/agent-harness-scaling-its-capabilities)). +It builds on Post 2's personal finance assistant and makes it *more capable* along four axes. + +## What this sample demonstrates + +- **Skills** — finance know-how (`valuation`, `risk-scoring`) is packaged as discoverable `SKILL.md` + files under `skills/`, which the agent loads on demand. The sample builds its own provider with + `AgentSkillsProviderBuilder.UseFileSkills([skillsDir], scriptRunner: new SubprocessScriptRunner().RunAsync)` + so the skills' Python scripts can run, and sets `DisableAgentSkillsProvider = true` to replace the + harness default. Optionally folds in centrally-managed **Foundry skills** discovered live from a + Foundry **Toolbox MCP** endpoint via `FoundrySkills.ConnectAsync(...)` + `UseMcpSkills(...)` + (opt-in; see below). +- **Shell** — a `LocalShellExecutor` confined to the trade-confirmation vault + (`working/confirmations/`) lets the agent tidy the accumulated confirmation files (reorganize into + `year/month`, rename to `YYYY-MM-DD_TICKER_BUY|SELL.txt`). `ConfineWorkingDirectory` re-anchors + every command to the vault and a `ShellPolicy` deny-list pre-filters obviously destructive + commands. Exposed as the `run_shell` tool, which prompts for approval before each command runs. + (The deny-list is a UX guardrail, not a security boundary — for hard isolation use a + `DockerShellExecutor`.) +- **CodeAct** — a `HyperlightCodeActProvider` gives the agent a sandboxed Python interpreter to + crunch portfolio numbers by writing and running code. It runs on Hyperlight (a micro-VM), so it + requires hardware virtualization. The guest module path is resolved automatically from the + `Hyperlight.HyperlightSandbox.Guest.Python` NuGet package via `PythonGuestModule.GetModulePath()`. +- **Background agents** — a lean, web-search-only `ResearchAgent` is registered via + `HarnessAgentOptions.BackgroundAgents`, exposing the `background_agents_*` tools so the main agent + can fan out per-ticker research concurrently and aggregate the findings. + +## Prerequisites + +1. A Microsoft Foundry project with a deployed model (e.g. `gpt-5.4`). +2. Azure CLI installed and authenticated (`az login`). +3. *(For CodeAct)* a host with hardware virtualization enabled (Hyperlight runs the Python + interpreter in a micro-VM). + +## Environment variables + +```bash +export FOUNDRY_PROJECT_ENDPOINT="https://your-project.services.ai.azure.com/api/projects/your-project" +# Optional (defaults to gpt-5.4) +export FOUNDRY_MODEL="gpt-5.4" + +# Optional — enable centrally-managed Foundry skills (Foundry Toolbox MCP endpoint URL): +export FOUNDRY_TOOLBOX_MCP_SERVER_URL="https://your-project.services.ai.azure.com/.../toolboxes/your-toolbox/mcp?api-version=v1" +``` + +When `FOUNDRY_TOOLBOX_MCP_SERVER_URL` is not set, the sample runs with the local file skills only and +prints a note. + +## Running + +```bash +cd dotnet +dotnet run --project samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities +``` + +## What to expect + +The sample starts an interactive loop in **execute** mode (quick lookups don't need a plan). Try +these in order: + +1. `Value MSFT for me.` — the agent loads the `valuation` skill and follows its instructions + (reading references and running its script). +2. `Score the risk of my portfolio.` — the agent reads `portfolio.csv` and loads the `risk-scoring` + skill. +3. `/mode plan`, then `Tidy up my trade confirmations.` — switching to plan mode first makes the + agent inspect `working/confirmations/` and propose a reorganization plan before touching anything; + once you approve it switches to execute and uses the shell to reorganize and rename the files, + **prompting you to approve** each command. +4. `Work out the total value of my portfolio.` — the agent writes and runs Python via CodeAct. +5. `Research MSFT, NVDA and SPY and summarize the latest news.` — the agent fans the tickers out to + the background research agent and aggregates the results. +6. `What's the capital of France?` — with a `financial-agent-rules` skill published to your Foundry + toolbox and Foundry skills enabled (`FOUNDRY_TOOLBOX_MCP_SERVER_URL`), the agent loads it, + recognizes the question is off-topic, and politely declines, steering you back to finance. + +See the [Part 3 blog post](https://devblogs.microsoft.com/agent-framework/agent-harness-scaling-its-capabilities) +for more on the `financial-agent-rules` skill — including the SKILL.md to publish to your Foundry toolbox. diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/ResearchAgent.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/ResearchAgent.cs new file mode 100644 index 00000000000..3d8ba56ff9c --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/ResearchAgent.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft. All rights reserved. + +using Microsoft.Agents.AI; +using Microsoft.Extensions.AI; + +namespace ClawSample; + +/// +/// Builds the background "research" agent that the main claw fans work out to. +/// +/// +/// This sub-agent doesn't need any of the harness machinery, so it's a plain +/// with a single tool: the hosted web search. The parent claw +/// delegates a per-ticker research task to one of these and they run concurrently. +/// +internal static class ResearchAgent +{ + /// Creates a web-search-only background agent for delegated ticker research. + /// The chat client the background agent should use. + public static AIAgent Create(IChatClient chatClient) => + chatClient.AsAIAgent( + instructions: + "You research a single stock ticker. Use the web search tool to find the most " + + "recent, relevant news and commentary, then return a short, factual summary " + + "(3-4 bullet points) with no preamble.", + name: "TickerResearchAgent", + description: "Searches the web for recent news and commentary about a single stock ticker.", + // The only tool it needs: the same hosted web search the harness would have added. + tools: [new HostedWebSearchTool()]); +} diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/StockTools.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/StockTools.cs new file mode 100644 index 00000000000..bbac78ac087 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/StockTools.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ComponentModel; +using Microsoft.Extensions.AI; + +namespace ClawSample; + +/// +/// A custom function tool that gives our "claw" access to (illustrative) stock prices. +/// +/// +/// The prices and earnings figures returned here are mock data for demonstration purposes only and +/// are not real market quotes. In a real assistant you would call a market-data API instead. The +/// trailing earnings-per-share value is included so the valuation skill has something to work with. +/// +internal static class StockTools +{ + /// A delayed, illustrative stock quote, including a trailing earnings-per-share figure. + public sealed record StockQuote(string Symbol, decimal Price, decimal TrailingEps, string Currency, DateTimeOffset AsOf); + + // A tiny in-memory book of (price, trailing EPS) so the sample runs without any external dependency. + private static readonly Dictionary s_priceBook = new(StringComparer.OrdinalIgnoreCase) + { + ["MSFT"] = (462.97m, 11.80m), + ["AAPL"] = (229.35m, 6.13m), + ["GOOGL"] = (178.12m, 7.54m), + ["AMZN"] = (201.45m, 4.18m), + ["NVDA"] = (134.81m, 2.95m), + ["SPY"] = (612.40m, 23.10m), + }; + + /// + /// Gets the latest (delayed, illustrative) stock price and trailing EPS for a ticker symbol. + /// + /// The stock ticker symbol, e.g. MSFT or AAPL. + [Description("Gets the latest (delayed, illustrative) stock price and trailing earnings per share for a ticker symbol.")] + public static StockQuote GetStockPrice( + [Description("The stock ticker symbol, e.g. MSFT or AAPL.")] string symbol) + { + if (!s_priceBook.TryGetValue(symbol, out var data)) + { + // Deterministic pseudo-values for unknown symbols so the sample stays self-contained. + // Derive a stable seed from the characters — string.GetHashCode() is randomized per + // process and Math.Abs(int.MinValue) throws, so neither is safe for repeatable output. + var seed = 0; + foreach (var ch in symbol.ToUpperInvariant()) + { + seed = (seed * 31 + ch) % 1_000_000; + } + + var price = 50m + seed % 45000 / 100m; + data = (price, Math.Round(price / 20m, 2)); + } + + return new StockQuote(symbol.ToUpperInvariant(), data.Price, data.Eps, "USD", DateTimeOffset.UtcNow); + } + + /// Creates the wrapper used to expose the tool to the agent. + public static AIFunction CreateGetStockPriceTool() => AIFunctionFactory.Create(GetStockPrice, "get_stock_price"); +} diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/SubprocessScriptRunner.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/SubprocessScriptRunner.cs new file mode 100644 index 00000000000..39ac8d19e7f --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/SubprocessScriptRunner.cs @@ -0,0 +1,177 @@ +// Copyright (c) Microsoft. All rights reserved. + +// Sample subprocess-based skill script runner. +// Executes file-based skill scripts as local subprocesses. +// This is provided for demonstration purposes only. + +using System.Diagnostics; +using System.Text.Json; +using Microsoft.Agents.AI; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Abstractions; + +/// +/// Executes file-based skill scripts as local subprocesses. +/// +/// +/// This runner uses the script's absolute path and converts the arguments +/// to CLI arguments. When the LLM sends a JSON array, each element is used +/// as a positional argument. It is intended for demonstration purposes only. +/// +internal sealed class SubprocessScriptRunner +{ + private readonly ILogger _logger; + + /// + /// Initializes a new instance of the class. + /// + /// + /// Optional logger factory. When provided, script outcomes (success output, stderr, non-zero + /// exit codes, and failures) are written to the log in addition to being returned to the LLM. + /// + public SubprocessScriptRunner(ILoggerFactory? loggerFactory = null) + { + this._logger = (loggerFactory ?? NullLoggerFactory.Instance).CreateLogger(); + } + + /// + /// Runs a skill script as a local subprocess. + /// + public async Task RunAsync( + AgentFileSkill skill, + AgentFileSkillScript script, + JsonElement? arguments, + IServiceProvider? serviceProvider, + CancellationToken cancellationToken) + { + this._logger.LogDebug("Running script '{ScriptName}' from skill '{SkillName}'.", script.Name, skill.Frontmatter.Name); + + if (!File.Exists(script.FullPath)) + { + this._logger.LogError("Script file not found for skill '{SkillName}': {ScriptPath}", skill.Frontmatter.Name, script.FullPath); + return $"Error: Script file not found: {script.FullPath}"; + } + + string extension = Path.GetExtension(script.FullPath); + string? interpreter = extension switch + { + ".py" => "python3", + ".js" => "node", + ".sh" => "bash", + ".ps1" => "pwsh", + _ => null, + }; + + var startInfo = new ProcessStartInfo + { + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + WorkingDirectory = Path.GetDirectoryName(script.FullPath) ?? ".", + }; + + if (interpreter is not null) + { + startInfo.FileName = interpreter; + startInfo.ArgumentList.Add(script.FullPath); + } + else + { + startInfo.FileName = script.FullPath; + } + + if (arguments is { ValueKind: JsonValueKind.Array } json) + { + // Positional CLI arguments + foreach (var element in json.EnumerateArray()) + { + if (element.ValueKind != JsonValueKind.String) + { + throw new InvalidOperationException( + $"File-based skill scripts only accept string CLI arguments but received a JSON element of kind '{element.ValueKind}'. " + + "All array elements must be JSON strings."); + } + + startInfo.ArgumentList.Add(element.GetString()!); + } + } + else if (arguments is not null && arguments.Value.ValueKind != JsonValueKind.Null && arguments.Value.ValueKind != JsonValueKind.Undefined) + { + throw new InvalidOperationException( + $"Expected a JSON array of CLI arguments but received {arguments.Value.ValueKind}. " + + "File-based skill scripts expect positional arguments as a JSON array of strings."); + } + + Process? process = null; + try + { + process = Process.Start(startInfo); + if (process is null) + { + this._logger.LogError("Failed to start process for script '{ScriptName}' from skill '{SkillName}'.", script.Name, skill.Frontmatter.Name); + return $"Error: Failed to start process for script '{script.Name}'."; + } + + Task outputTask = process.StandardOutput.ReadToEndAsync(cancellationToken); + Task errorTask = process.StandardError.ReadToEndAsync(cancellationToken); + + await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false); + + string output = await outputTask.ConfigureAwait(false); + string error = await errorTask.ConfigureAwait(false); + + if (!string.IsNullOrEmpty(error)) + { + if (process.ExitCode == 0) + { + this._logger.LogWarning( + "Script '{ScriptName}' from skill '{SkillName}' succeeded but wrote to stderr:\n{Stderr}", + script.Name, skill.Frontmatter.Name, error.Trim()); + } + + output += $"\nStderr:\n{error}"; + } + + if (process.ExitCode != 0) + { + this._logger.LogError( + "Script '{ScriptName}' from skill '{SkillName}' exited with code {ExitCode}.{Stderr}", + script.Name, skill.Frontmatter.Name, process.ExitCode, + string.IsNullOrEmpty(error) ? string.Empty : $"\nStderr:\n{error.Trim()}"); + + output += $"\nScript exited with code {process.ExitCode}"; + } + + string result = string.IsNullOrEmpty(output) ? "(no output)" : output.Trim(); + + if (process.ExitCode == 0) + { + this._logger.LogInformation( + "Script '{ScriptName}' from skill '{SkillName}' completed successfully. Output:\n{Output}", + script.Name, skill.Frontmatter.Name, result); + } + + return result; + } + catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + { + // Kill the process on cancellation to avoid leaving orphaned subprocesses. + process?.Kill(entireProcessTree: true); + throw; + } + catch (OperationCanceledException) + { + throw; + } + catch (Exception ex) + { + this._logger.LogError(ex, "Failed to execute script '{ScriptName}' from skill '{SkillName}'.", script.Name, skill.Frontmatter.Name); + return $"Error: Failed to execute script '{script.Name}': {ex.Message}"; + } + finally + { + process?.Dispose(); + } + } +} diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/TradingTools.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/TradingTools.cs new file mode 100644 index 00000000000..b17ba8f6dc2 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/TradingTools.cs @@ -0,0 +1,55 @@ +// Copyright (c) Microsoft. All rights reserved. + +using System.ComponentModel; +using Microsoft.Extensions.AI; + +namespace ClawSample; + +/// +/// Sensitive "claw" tools that take real-world actions and therefore require human approval. +/// +/// +/// These tools only simulate their effects (no orders are placed, no email is sent). They exist +/// to demonstrate how the harness gates risky actions behind an approval prompt. +/// +internal static class TradingTools +{ + // + /// + /// Places a (simulated) buy or sell order for a given symbol and quantity. + /// + /// The stock ticker symbol to trade, e.g. MSFT. + /// Either buy or sell. + /// The number of shares to trade. + [Description("Places a buy or sell order for a given symbol and quantity.")] + public static string PlaceTrade( + [Description("The stock ticker symbol to trade, e.g. MSFT.")] string symbol, + [Description("Either 'buy' or 'sell'.")] string action, + [Description("The number of shares to trade.")] int quantity) + { + var isBuy = action.Equals("buy", StringComparison.OrdinalIgnoreCase); + var isSell = action.Equals("sell", StringComparison.OrdinalIgnoreCase); + if (!isBuy && !isSell) + { + return $"Invalid action '{action}'. Use 'buy' or 'sell'."; + } + + if (quantity <= 0) + { + return $"Invalid quantity '{quantity}'. Quantity must be a positive whole number of shares."; + } + + var verb = isSell ? "Sold" : "Bought"; + var confirmation = $"TRADE-{Guid.NewGuid().ToString("N")[..8].ToUpperInvariant()}"; + return $"{verb} {quantity} share(s) of {symbol.ToUpperInvariant()}. Confirmation: {confirmation}."; + } + // + + /// + /// Creates an approval-required for . + /// Wrapping the function in tells the harness to + /// surface an approval request before the function ever runs. + /// + public static AIFunction CreatePlaceTradeTool() => + new ApprovalRequiredAIFunction(AIFunctionFactory.Create(PlaceTrade, "place_trade")); +} diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/SKILL.md b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/SKILL.md new file mode 100644 index 00000000000..3ced6ba1c5e --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/SKILL.md @@ -0,0 +1,18 @@ +--- +name: risk-scoring +description: Score how concentrated and risky a portfolio is on a 0-100 scale from its position weights. Use when the user asks how risky their portfolio is, whether it is too concentrated, or for a diversification check. +--- + +## Usage + +When the user asks about portfolio risk or concentration: + +1. Read `references/risk-bands.md` to understand the score bands and what drives them. +2. Compute each holding's market value (shares × price) — use the `get_stock_price` tool for current + prices if you do not already have them. +3. Run `scripts/risk_score.py` with one `--position VALUE` argument per holding, + e.g. `--position 18518 --position 17201 --position 16177`. +4. Report the 0-100 score, the band it falls in, and the largest single-position weight, then suggest + (in general terms) whether the portfolio looks well diversified or concentrated. + +Remind the user this is a crude concentration measure, not a complete risk model, and not advice. diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/references/risk-bands.md b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/references/risk-bands.md new file mode 100644 index 00000000000..a2beec75ba1 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/references/risk-bands.md @@ -0,0 +1,27 @@ +# Risk-scoring guide (illustrative) + +This skill scores **concentration risk** — how much a portfolio depends on its largest positions — +on a 0-100 scale, where higher means riskier. + +## How the score is built + +1. Convert each position to a weight: `weight = position_value / total_value`. +2. Compute the Herfindahl-Hirschman Index (HHI): `HHI = sum(weight^2)`. + - A perfectly even portfolio of *n* holdings has `HHI = 1/n` (low). + - A single-stock portfolio has `HHI = 1` (maximum concentration). +3. Scale to 0-100: `score = round(HHI * 100)`. + +## Score bands + +| Score | Band | Interpretation | +|---------|--------------------|-------------------------------------------------| +| 0-20 | Well diversified | No single holding dominates. | +| 21-40 | Moderately diversified | Some tilt, but broadly spread. | +| 41-60 | Concentrated | A few positions carry most of the risk. | +| 61-100 | Highly concentrated| Heavily dependent on one or two positions. | + +Also watch the **largest single-position weight**: above ~25% is usually worth flagging regardless +of the overall score. + +This measures concentration only — it ignores volatility, correlation, sector exposure, and leverage, +so it is a starting point, not a verdict. diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/scripts/risk_score.py b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/scripts/risk_score.py new file mode 100644 index 00000000000..a449b03f164 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/risk-scoring/scripts/risk_score.py @@ -0,0 +1,54 @@ +# Portfolio risk-scoring script +# Scores concentration risk on a 0-100 scale using the Herfindahl-Hirschman Index (HHI). +# +# weight_i = position_i / total +# HHI = sum(weight_i ^ 2) +# score = round(HHI * 100) # higher = more concentrated = riskier +# +# Usage: +# python scripts/risk_score.py --position 18518 --position 17201 --position 16177 + +import argparse +import json + + +def main() -> None: + parser = argparse.ArgumentParser(description="Score portfolio concentration risk (0-100).") + parser.add_argument( + "--position", + type=float, + action="append", + required=True, + help="Market value of one holding. Pass once per position.", + ) + args = parser.parse_args() + + positions = [p for p in args.position if p > 0] + total = sum(positions) + if total <= 0: + print(json.dumps({"error": "Total portfolio value must be positive."})) + return + + weights = [p / total for p in positions] + hhi = sum(w * w for w in weights) + score = round(hhi * 100) + + if score <= 20: + band = "Well diversified" + elif score <= 40: + band = "Moderately diversified" + elif score <= 60: + band = "Concentrated" + else: + band = "Highly concentrated" + + print(json.dumps({ + "positions": len(positions), + "score": score, + "band": band, + "largest_weight_pct": round(max(weights) * 100, 1), + })) + + +if __name__ == "__main__": + main() diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/SKILL.md b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/SKILL.md new file mode 100644 index 00000000000..d84b57ebb14 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/SKILL.md @@ -0,0 +1,17 @@ +--- +name: valuation +description: Estimate whether a stock looks cheap or expensive using a price-to-earnings (P/E) based fair-value method. Use when the user asks if a stock is over- or under-valued, or for a fair-value / target price. +--- + +## Usage + +When the user asks whether a stock is fairly valued, over-valued, or under-valued: + +1. Read `references/valuation-guide.md` to pick a sensible target P/E for the company's sector. +2. Run `scripts/valuation_metrics.py` with the current price, trailing EPS, and the target P/E, + e.g. `--price 462.97 --eps 11.80 --target-pe 32`. +3. Report the computed P/E, the fair-value estimate, and the percentage upside/downside, then state + plainly whether the stock looks cheap or expensive on this measure. + +Always remind the user that a single P/E heuristic is not investment advice and ignores growth, +debt, and many other factors. diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/references/valuation-guide.md b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/references/valuation-guide.md new file mode 100644 index 00000000000..f6858ac0fc4 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/references/valuation-guide.md @@ -0,0 +1,28 @@ +# Valuation guide (illustrative) + +A quick price-to-earnings (P/E) sanity check: + +- **P/E = price ÷ trailing earnings per share (EPS)** +- **Fair value = trailing EPS × target P/E** +- **Upside/downside = (fair value − price) ÷ price** + +## Typical target P/E by sector + +These are rough, illustrative anchors only — not live market multiples. + +| Sector | Conservative target P/E | Growth target P/E | +|-----------------------|-------------------------|-------------------| +| Mega-cap technology | 28 | 35 | +| Semiconductors | 25 | 40 | +| Consumer staples | 18 | 22 | +| Financials / banks | 11 | 14 | +| Broad market (index) | 19 | 21 | + +## How to read the result + +- Fair value **well above** the current price ⇒ the stock looks **cheap** on this measure. +- Fair value **well below** the current price ⇒ the stock looks **expensive** on this measure. +- Within ~5% ⇒ roughly **fairly valued**. + +This is one crude lens. It ignores growth rates, balance-sheet strength, and cash flow, so never +present it as a recommendation. diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/scripts/valuation_metrics.py b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/scripts/valuation_metrics.py new file mode 100644 index 00000000000..896f6487354 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/scripts/valuation_metrics.py @@ -0,0 +1,49 @@ +# Valuation metrics script +# Computes a simple price-to-earnings (P/E) based fair-value estimate. +# +# fair_value = eps * target_pe +# pe = price / eps +# upside = (fair_value - price) / price +# +# Usage: +# python scripts/valuation_metrics.py --price 462.97 --eps 11.80 --target-pe 32 + +import argparse +import json + + +def main() -> None: + parser = argparse.ArgumentParser(description="Compute a P/E based fair-value estimate.") + parser.add_argument("--price", type=float, required=True, help="Current share price.") + parser.add_argument("--eps", type=float, required=True, help="Trailing earnings per share.") + parser.add_argument("--target-pe", type=float, required=True, help="Target P/E from the guide.") + args = parser.parse_args() + + if args.eps <= 0: + print(json.dumps({"error": "EPS must be positive to compute a P/E ratio."})) + return + + pe = args.price / args.eps + fair_value = args.eps * args.target_pe + upside = (fair_value - args.price) / args.price + + if upside > 0.05: + verdict = "looks cheap" + elif upside < -0.05: + verdict = "looks expensive" + else: + verdict = "roughly fairly valued" + + print(json.dumps({ + "price": round(args.price, 2), + "eps": round(args.eps, 2), + "target_pe": round(args.target_pe, 2), + "pe": round(pe, 2), + "fair_value": round(fair_value, 2), + "upside_pct": round(upside * 100, 1), + "verdict": verdict, + })) + + +if __name__ == "__main__": + main() diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/2025-06-21_nvda.txt b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/2025-06-21_nvda.txt new file mode 100644 index 00000000000..6350a8f7d2a --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/2025-06-21_nvda.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-55AA44BB +Date: 2025-06-21 +Symbol: NVDA +Action: SELL +Quantity: 20 diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/SPY sell.txt b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/SPY sell.txt new file mode 100644 index 00000000000..14305ca985c --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/SPY sell.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-77CC88DD +Date: 2024-05-08 +Symbol: SPY +Action: SELL +Quantity: 15 diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/conf_AAPL.txt b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/conf_AAPL.txt new file mode 100644 index 00000000000..a4655401d92 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/conf_AAPL.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-9F8E7D6C +Date: 2024-11-03 +Symbol: AAPL +Action: BUY +Quantity: 75 diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/copy of trade (3).txt b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/copy of trade (3).txt new file mode 100644 index 00000000000..28fb391fd59 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/copy of trade (3).txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-1234ABCD +Date: 2025-09-12 +Symbol: AMZN +Action: BUY +Quantity: 30 diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/googl-jan.txt b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/googl-jan.txt new file mode 100644 index 00000000000..d8c0470002d --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/googl-jan.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-EE11FF22 +Date: 2025-01-30 +Symbol: GOOGL +Action: BUY +Quantity: 25 diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/trade confirmation 1.txt b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/trade confirmation 1.txt new file mode 100644 index 00000000000..2d3f305d85b --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/trade confirmation 1.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-A1B2C3D4 +Date: 2024-02-14 +Symbol: MSFT +Action: BUY +Quantity: 40 diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/portfolio.csv b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/portfolio.csv new file mode 100644 index 00000000000..d2e0fbad5e9 --- /dev/null +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/portfolio.csv @@ -0,0 +1,7 @@ +symbol,shares,cost_basis,purchase_date +MSFT,40,312.50,2023-02-14 +AAPL,75,168.20,2022-11-03 +NVDA,120,42.80,2021-06-21 +AMZN,30,142.10,2023-09-12 +GOOGL,25,128.45,2024-01-30 +SPY,60,418.90,2024-05-08 diff --git a/dotnet/samples/02-agents/Harness/README.md b/dotnet/samples/02-agents/Harness/README.md index 54338aba6bb..1cb84a8410c 100644 --- a/dotnet/samples/02-agents/Harness/README.md +++ b/dotnet/samples/02-agents/Harness/README.md @@ -18,3 +18,4 @@ Samples accompanying the [*Build your own agent harness or claw with Microsoft A | Sample | Description | | --- | --- | | [Claw_Step01_MeetYourClaw](./BuildYourOwnClaw/Claw_Step01_MeetYourClaw/README.md) | Post 1 — a minimal HarnessAgent with a custom `get_stock_price` tool, web search, and planning | +| [Claw_Step03_ScalingCapabilities](./BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/README.md) | Post 3 — scaling the claw with skills (plus optional Foundry skills), a confined shell, CodeAct, and background agents | diff --git a/python/samples/02-agents/harness/build_your_own_claw/README.md b/python/samples/02-agents/harness/build_your_own_claw/README.md index 49413a3b37a..05e3110c591 100644 --- a/python/samples/02-agents/harness/build_your_own_claw/README.md +++ b/python/samples/02-agents/harness/build_your_own_claw/README.md @@ -6,6 +6,7 @@ series. Each step builds a personal finance / investing assistant on top of directory. - **Part 1 — `claw_step01_meet_your_claw.py`** — the minimal harness. +- **Part 3 — `claw_step03_scaling_capabilities.py`** — skills, shell, CodeAct, and background agents. ## Prerequisites @@ -59,3 +60,61 @@ The sample starts an interactive loop. Try these in order: --- +## Part 3 — Scaling its capabilities + +Makes the assistant *more capable* along four axes. + +### What this sample demonstrates + +- **Skills** — finance know-how (`valuation`, `risk-scoring`) is packaged as discoverable + `SKILL.md` files under `skills/`, which the agent loads on demand. The sample builds a + `FileSkillsSource(..., script_runner=subprocess_script_runner)` so the skills' Python + scripts can run. Optionally folds in centrally-managed **Foundry skills** served from a + Foundry Toolbox MCP endpoint via `MCPSkillsSource` (opt-in; see below). +- **Shell** — a `LocalShellTool` confined to the trade-confirmation vault + (`working/confirmations/`) lets the agent tidy the accumulated confirmation files (reorganize into + `year/month`, rename to `YYYY-MM-DD_TICKER_BUY|SELL.txt`). Guarded by a `ShellPolicy` deny-list + **and** a confined working directory; left at the default + `approval_mode="always_require"` so each command is surfaced for approval. +- **CodeAct** — a `MontyCodeActProvider` gives the agent a sandboxed, cross-platform Python + interpreter to crunch portfolio numbers by writing and running code. +- **Background agents** — a lean, web-search-only `TickerResearchAgent` is registered via + `create_harness_agent(background_agents=[...])`, so the main agent can fan out per-ticker research + concurrently and aggregate the findings. + +### Additional environment variables (optional) + +```bash +# Enable centrally-managed Foundry skills (Foundry Toolbox MCP endpoint URL): +export FOUNDRY_TOOLBOX_MCP_SERVER_URL="https://.services.ai.azure.com/.../toolboxes//mcp?api-version=v1" +``` + +When this is not set, the sample runs with the local file skills only, and prints a note. + +### Running + +```bash +uv run python/samples/02-agents/harness/build_your_own_claw/claw_step03_scaling_capabilities.py +``` + +### What to expect + +Try these in order (the sample starts in **execute** mode — quick lookups don't need a plan): + +1. `Value MSFT for me.` — the agent loads the `valuation` skill and follows its instructions + (reading references and running its script). +2. `Score the risk of my portfolio.` — the agent reads `portfolio.csv` and loads the `risk-scoring` + skill. +3. `/mode plan`, then `Tidy up my trade confirmations.` — switching to plan mode first makes the + agent inspect `working/confirmations/` and propose a reorganization plan before touching anything; + once you approve it switches to execute and uses the shell to reorganize and rename the files, + **prompting you to approve** each command. +4. `Work out the total value of my portfolio.` — the agent writes and runs Python via CodeAct. +5. `Research MSFT, NVDA and SPY and summarize the latest news.` — the agent fans the tickers out to + the background research agent and aggregates the results. +6. `What's the capital of France?` — with a `financial-agent-rules` skill published to your Foundry + toolbox and Foundry skills enabled (`FOUNDRY_TOOLBOX_MCP_SERVER_URL`), the agent loads it, + recognizes the question is off-topic, and politely declines, steering you back to finance. + +See the [Part 3 blog post](https://devblogs.microsoft.com/agent-framework/agent-harness-scaling-its-capabilities) +for more on the `financial-agent-rules` skill — including the SKILL.md to publish to your Foundry toolbox. diff --git a/python/samples/02-agents/harness/build_your_own_claw/claw_step03_scaling_capabilities.py b/python/samples/02-agents/harness/build_your_own_claw/claw_step03_scaling_capabilities.py new file mode 100644 index 00000000000..b0eb5135f98 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/claw_step03_scaling_capabilities.py @@ -0,0 +1,339 @@ +# /// script +# requires-python = ">=3.10" +# dependencies = [ +# "agent-framework", +# "agent-framework-tools", +# "agent-framework-monty", +# "mcp", +# "httpx", +# "textual>=6.2.1", +# "rich>=13.7.1", +# "azure-identity", +# "python-dotenv", +# ] +# /// +# Run with any PEP 723 compatible runner, e.g.: +# uv run python/samples/02-agents/harness/build_your_own_claw/claw_step03_scaling_capabilities.py + +# Copyright (c) Microsoft. All rights reserved. + +"""Scaling its capabilities (Post 3) — Python. + +The third runnable sample from the "Build your own claw and agent harness with Microsoft Agent +Framework" blog series. See: https://devblogs.microsoft.com/agent-framework/agent-harness-scaling-its-capabilities. +It builds on Post 2's personal finance assistant and makes it *more capable* in four ways: + +1. Skills — package finance know-how (valuation, risk-scoring) as discoverable SKILL.md + files the agent loads on demand. Optionally fold in centrally-managed Foundry + skills served from a Foundry Toolbox MCP endpoint (opt-in via + FOUNDRY_TOOLBOX_MCP_SERVER_URL). +2. Shell — a sandboxed shell, confined to the trade-confirmation vault, that the agent uses + to reorganize the accumulated confirmation files (year/month, rename, archive). + Guarded by an allow/deny-list policy and a confined working directory. +3. CodeAct — the agent writes and runs Python to crunch portfolio numbers, using the + cross-platform Monty interpreter. +4. Background agents — fan out a per-ticker research sub-agent so several tickers are researched + concurrently, then aggregated. + +This sample reuses the shared harness ``console`` package in the parent ``harness/`` directory. + +Environment variables: + FOUNDRY_PROJECT_ENDPOINT — Microsoft Foundry project endpoint URL + FOUNDRY_MODEL — Model deployment name (defaults to gpt-5.4) + FOUNDRY_TOOLBOX_MCP_SERVER_URL — (optional) Foundry Toolbox MCP endpoint URL; enables Foundry skills + +Authentication: + Run ``az login`` before running this sample. +""" + +import asyncio +import os +import sys +import uuid +from collections.abc import Callable, Generator +from contextlib import AsyncExitStack +from datetime import datetime, timezone +from pathlib import Path +from typing import Annotated, Any, Literal + +import httpx +from agent_framework import ( + AggregatingSkillsSource, + Agent, + AgentModeProvider, + DeduplicatingSkillsSource, + FileAccessProvider, + FileSkillsSource, + FileSystemAgentFileStore, + MCPSkillsSource, + SkillsProvider, + SkillsSource, + create_harness_agent, + tool, +) +from agent_framework.foundry import FoundryChatClient +from agent_framework_monty import MontyCodeActProvider +from agent_framework_tools.shell import LocalShellTool, ShellPolicy +from azure.identity import AzureCliCredential, get_bearer_token_provider +from dotenv import load_dotenv +from mcp.client.session import ClientSession +from mcp.client.streamable_http import streamable_http_client +from pydantic import Field + +# Reuse the shared harness console that lives in the parent ``harness/`` directory, and the local +# subprocess script runner used to execute file-based skill scripts. +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) +from console import build_observers_with_planning, run_agent_async # noqa: E402 + +from subprocess_script_runner import subprocess_script_runner # noqa: E402 + +_SAMPLE_DIR = Path(__file__).resolve().parent +_WORKING_DIR = _SAMPLE_DIR / "working" +_VAULT_DIR = _WORKING_DIR / "confirmations" +_SKILLS_DIR = _SAMPLE_DIR / "skills" + +FINANCE_INSTRUCTIONS = """\ +## Personal Finance Assistant Instructions + +You are a personal finance and investing assistant. You help the user understand their portfolio +and watchlist, value individual stocks, gauge portfolio risk, research the market, and keep their +records tidy. + +### Working style + +- The user's holdings live in a file called portfolio.csv. Read it with the file_access tools + before answering questions about their portfolio, and never modify it unless asked. +- You have skills for valuation and risk-scoring. When a question matches a skill, load it and + follow its instructions (read its references, run its scripts) rather than guessing. +- When asked to research several tickers, delegate each one to the background research agent so + they run concurrently, then summarize the findings together. +- The user's trade confirmations accumulate in the working/confirmations folder. When asked to tidy + or reorganize them, use the run_shell tool: inspect the folder first, then move files into a + year/month layout and rename them to YYYY-MM-DD_TICKER_BUY|SELL.txt. Explain your plan before + running commands that change anything. +- To buy or sell, use the place_trade tool. This takes a real action, so the user will be asked to + approve it before it runs — explain what you are about to do first. + +### Important + +You provide information and analysis only — you are not a licensed financial advisor and you must +not present your output as personalized investment advice. Remind the user to do their own +research before making decisions. +""" + +# A tiny in-memory book of (price, trailing EPS) so the sample runs without any external dependency. +# These are illustrative mock values, not real market data. +_PRICE_BOOK: dict[str, tuple[float, float]] = { + "MSFT": (462.97, 11.80), + "AAPL": (229.35, 6.13), + "GOOGL": (178.12, 7.54), + "AMZN": (201.45, 4.18), + "NVDA": (134.81, 2.95), + "SPY": (612.40, 23.10), +} + + +# +def get_stock_price( + symbol: Annotated[str, "The stock ticker symbol, e.g. MSFT or AAPL."], +) -> dict[str, object]: + """Get the latest (delayed, illustrative) stock price and trailing EPS for a ticker symbol.""" + ticker = symbol.upper() + data = _PRICE_BOOK.get(ticker) + if data is None: + # Deterministic pseudo-values for unknown symbols so the sample stays self-contained. + # The built-in hash() is randomized per process (PYTHONHASHSEED), so derive a stable seed. + seed = 0 + for ch in ticker: + seed = (seed * 31 + ord(ch)) % 1_000_000 + price = 50.0 + (seed % 45000) / 100.0 + data = (price, round(price / 20.0, 2)) + + return { + "symbol": ticker, + "price": round(data[0], 2), + "trailing_eps": round(data[1], 2), + "currency": "USD", + "as_of": datetime.now(timezone.utc).isoformat(), + } +# + + +# +@tool(approval_mode="always_require") +def place_trade( + symbol: Annotated[str, "The stock ticker symbol to trade, e.g. MSFT."], + action: Annotated[Literal["buy", "sell"], "Either 'buy' or 'sell'."], + quantity: Annotated[int, Field(gt=0, description="The number of shares to trade.")], +) -> str: + """Place a (simulated) buy or sell order. Marked approval-required, so the harness asks the + user to approve before this ever runs. No real order is placed. + + ``action`` and ``quantity`` are validated by the framework (pydantic) from their type hints: + the model can only pass 'buy'/'sell' and a quantity greater than zero. + """ + verb = "Sold" if action == "sell" else "Bought" + confirmation = f"TRADE-{uuid.uuid4().hex[:8].upper()}" + return f"{verb} {quantity} share(s) of {symbol.upper()}. Confirmation: {confirmation}." +# + + +# +async def _build_skills_provider(stack: AsyncExitStack) -> SkillsProvider: + """Build a skills provider over the local skills/ folder, plus optional Foundry-managed skills. + + File-based skills (valuation, risk-scoring) always load. When FOUNDRY_TOOLBOX_MCP_SERVER_URL is + set we also connect to a Foundry Toolbox MCP endpoint and surface its skills, so they can be + managed and updated centrally without changing this agent. + """ + # subprocess_script_runner lets the file-based skills run their Python scripts. + sources: list[SkillsSource] = [FileSkillsSource(str(_SKILLS_DIR), script_runner=subprocess_script_runner)] + + toolbox_url = os.environ.get("FOUNDRY_TOOLBOX_MCP_SERVER_URL") + if toolbox_url: + session = await _connect_foundry_toolbox(stack, toolbox_url) + sources.append(MCPSkillsSource(client=session)) + print("Foundry skills enabled (Toolbox MCP).") + else: + print("Foundry skills disabled. Set FOUNDRY_TOOLBOX_MCP_SERVER_URL to enable them.") + + source: SkillsSource = sources[0] if len(sources) == 1 else AggregatingSkillsSource(sources) + return SkillsProvider(DeduplicatingSkillsSource(source)) + + +class _ToolboxAuth(httpx.Auth): + """Attach a fresh Foundry bearer token to every request.""" + + def __init__(self, token_provider: Callable[[], str]): + self._get_token = token_provider + + def auth_flow(self, request: httpx.Request) -> Generator[httpx.Request, httpx.Response, None]: + request.headers["Authorization"] = f"Bearer {self._get_token()}" + yield request + + +async def _connect_foundry_toolbox(stack: AsyncExitStack, url: str) -> ClientSession: + """Open an MCP session against a Foundry Toolbox endpoint, tied to ``stack``'s lifetime.""" + token_provider = get_bearer_token_provider(AzureCliCredential(), "https://ai.azure.com/.default") + http_client = await stack.enter_async_context( + httpx.AsyncClient( + auth=_ToolboxAuth(token_provider), + headers={"Foundry-Features": "Toolboxes=V1Preview"}, + timeout=httpx.Timeout(30.0, read=300.0), + follow_redirects=True, + ) + ) + read, write, _ = await stack.enter_async_context(streamable_http_client(url=url, http_client=http_client)) + session = await stack.enter_async_context(ClientSession(read, write)) + await session.initialize() + return session +# + + +# +def _build_research_agent(client: FoundryChatClient) -> Any: + """Build the lean, web-search-only chat agent used for per-ticker research.""" + # This sub-agent doesn't need any harness machinery - it's a plain chat agent with a single + # tool: the same hosted web search the harness would have added. The parent still exposes the + # background_agents_* tools because it receives this agent via background_agents. + return Agent( + client=client, + name="TickerResearchAgent", + description="Searches the web for recent news and commentary about a single stock ticker.", + tools=[client.get_web_search_tool()], + instructions=( + "You research a single stock ticker. Use the web search tool to find the most recent, " + "relevant news and commentary, then return a short, factual summary (3-4 bullet points) " + "with no preamble." + ), + ) +# + + +# +def _build_shell() -> LocalShellTool: + """A sandboxed shell, confined to the trade-confirmation vault. + + ``confine_workdir`` re-anchors every command to the vault, and the deny-list pre-filters + obviously destructive command shapes. (Patterns are a UX guardrail, not a security boundary — + for hard isolation use DockerShellTool.) Left at the default ``approval_mode="always_require"`` + so each command is surfaced for approval. + """ + return LocalShellTool( + mode="persistent", + workdir=str(_VAULT_DIR), + confine_workdir=True, + policy=ShellPolicy( + denylist=[ + r"\brm\s+-rf\b", + r"\bsudo\b", + r":\(\)\s*\{", # fork-bomb shape + r"\bmkfs\b", + r">\s*/dev/sd", + ], + ), + timeout=15, + ) +# + + +async def main() -> None: + load_dotenv() + _WORKING_DIR.mkdir(exist_ok=True) + + # + # Construct a chat client (see Post 1). FoundryChatClient reads FOUNDRY_PROJECT_ENDPOINT and + # FOUNDRY_MODEL from the environment; AzureCliCredential handles auth (run `az login`). + client = FoundryChatClient(credential=AzureCliCredential()) + # + + async with AsyncExitStack() as stack: + skills_provider = await _build_skills_provider(stack) + research_agent = _build_research_agent(client) + shell = _build_shell() + + # + # CodeAct: a sandboxed Python interpreter the model can write and run code in to crunch + # numbers. Monty is a pure, cross-platform interpreter, so it needs no extra setup. + context_providers: list[Any] = [MontyCodeActProvider(approval_mode="never_require")] + print("CodeAct enabled (Monty).") + # + + # + # Turn the chat client into a harness agent. On top of Post 2's file access and approvals we + # add the four "scaling" capabilities: skills (our own provider), background agents, a + # confined shell, and optional CodeAct. Read-only file tools are auto-approved so reading the + # portfolio is frictionless while writes, trades, and shell commands still prompt. + agent = create_harness_agent( + client=client, + agent_instructions=FINANCE_INSTRUCTIONS, + tools=[get_stock_price, place_trade], + file_access_store=FileSystemAgentFileStore(str(_WORKING_DIR)), + skills_provider=skills_provider, + background_agents=[research_agent], + shell_executor=shell, + auto_approval_rules=[FileAccessProvider.read_only_tools_auto_approval_rule], + context_providers=context_providers, + mode_provider=AgentModeProvider(default_mode="execute"), + ) + # + + # + session = agent.create_session() + + # Run the interactive console session. The default planning observers already include a tool + # approval observer, so the place_trade and run_shell approval prompts are surfaced + # automatically. + await run_agent_async( + agent, + session=session, + observers=build_observers_with_planning(agent), + initial_mode="execute", + title="💹 Finance Assistant", + placeholder="Value a stock, score your portfolio risk, research tickers, or tidy your confirmations...", + ) + # + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/SKILL.md b/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/SKILL.md new file mode 100644 index 00000000000..3ced6ba1c5e --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/SKILL.md @@ -0,0 +1,18 @@ +--- +name: risk-scoring +description: Score how concentrated and risky a portfolio is on a 0-100 scale from its position weights. Use when the user asks how risky their portfolio is, whether it is too concentrated, or for a diversification check. +--- + +## Usage + +When the user asks about portfolio risk or concentration: + +1. Read `references/risk-bands.md` to understand the score bands and what drives them. +2. Compute each holding's market value (shares × price) — use the `get_stock_price` tool for current + prices if you do not already have them. +3. Run `scripts/risk_score.py` with one `--position VALUE` argument per holding, + e.g. `--position 18518 --position 17201 --position 16177`. +4. Report the 0-100 score, the band it falls in, and the largest single-position weight, then suggest + (in general terms) whether the portfolio looks well diversified or concentrated. + +Remind the user this is a crude concentration measure, not a complete risk model, and not advice. diff --git a/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/references/risk-bands.md b/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/references/risk-bands.md new file mode 100644 index 00000000000..a2beec75ba1 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/references/risk-bands.md @@ -0,0 +1,27 @@ +# Risk-scoring guide (illustrative) + +This skill scores **concentration risk** — how much a portfolio depends on its largest positions — +on a 0-100 scale, where higher means riskier. + +## How the score is built + +1. Convert each position to a weight: `weight = position_value / total_value`. +2. Compute the Herfindahl-Hirschman Index (HHI): `HHI = sum(weight^2)`. + - A perfectly even portfolio of *n* holdings has `HHI = 1/n` (low). + - A single-stock portfolio has `HHI = 1` (maximum concentration). +3. Scale to 0-100: `score = round(HHI * 100)`. + +## Score bands + +| Score | Band | Interpretation | +|---------|--------------------|-------------------------------------------------| +| 0-20 | Well diversified | No single holding dominates. | +| 21-40 | Moderately diversified | Some tilt, but broadly spread. | +| 41-60 | Concentrated | A few positions carry most of the risk. | +| 61-100 | Highly concentrated| Heavily dependent on one or two positions. | + +Also watch the **largest single-position weight**: above ~25% is usually worth flagging regardless +of the overall score. + +This measures concentration only — it ignores volatility, correlation, sector exposure, and leverage, +so it is a starting point, not a verdict. diff --git a/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/scripts/risk_score.py b/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/scripts/risk_score.py new file mode 100644 index 00000000000..a449b03f164 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/skills/risk-scoring/scripts/risk_score.py @@ -0,0 +1,54 @@ +# Portfolio risk-scoring script +# Scores concentration risk on a 0-100 scale using the Herfindahl-Hirschman Index (HHI). +# +# weight_i = position_i / total +# HHI = sum(weight_i ^ 2) +# score = round(HHI * 100) # higher = more concentrated = riskier +# +# Usage: +# python scripts/risk_score.py --position 18518 --position 17201 --position 16177 + +import argparse +import json + + +def main() -> None: + parser = argparse.ArgumentParser(description="Score portfolio concentration risk (0-100).") + parser.add_argument( + "--position", + type=float, + action="append", + required=True, + help="Market value of one holding. Pass once per position.", + ) + args = parser.parse_args() + + positions = [p for p in args.position if p > 0] + total = sum(positions) + if total <= 0: + print(json.dumps({"error": "Total portfolio value must be positive."})) + return + + weights = [p / total for p in positions] + hhi = sum(w * w for w in weights) + score = round(hhi * 100) + + if score <= 20: + band = "Well diversified" + elif score <= 40: + band = "Moderately diversified" + elif score <= 60: + band = "Concentrated" + else: + band = "Highly concentrated" + + print(json.dumps({ + "positions": len(positions), + "score": score, + "band": band, + "largest_weight_pct": round(max(weights) * 100, 1), + })) + + +if __name__ == "__main__": + main() diff --git a/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/SKILL.md b/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/SKILL.md new file mode 100644 index 00000000000..d84b57ebb14 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/SKILL.md @@ -0,0 +1,17 @@ +--- +name: valuation +description: Estimate whether a stock looks cheap or expensive using a price-to-earnings (P/E) based fair-value method. Use when the user asks if a stock is over- or under-valued, or for a fair-value / target price. +--- + +## Usage + +When the user asks whether a stock is fairly valued, over-valued, or under-valued: + +1. Read `references/valuation-guide.md` to pick a sensible target P/E for the company's sector. +2. Run `scripts/valuation_metrics.py` with the current price, trailing EPS, and the target P/E, + e.g. `--price 462.97 --eps 11.80 --target-pe 32`. +3. Report the computed P/E, the fair-value estimate, and the percentage upside/downside, then state + plainly whether the stock looks cheap or expensive on this measure. + +Always remind the user that a single P/E heuristic is not investment advice and ignores growth, +debt, and many other factors. diff --git a/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/references/valuation-guide.md b/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/references/valuation-guide.md new file mode 100644 index 00000000000..f6858ac0fc4 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/references/valuation-guide.md @@ -0,0 +1,28 @@ +# Valuation guide (illustrative) + +A quick price-to-earnings (P/E) sanity check: + +- **P/E = price ÷ trailing earnings per share (EPS)** +- **Fair value = trailing EPS × target P/E** +- **Upside/downside = (fair value − price) ÷ price** + +## Typical target P/E by sector + +These are rough, illustrative anchors only — not live market multiples. + +| Sector | Conservative target P/E | Growth target P/E | +|-----------------------|-------------------------|-------------------| +| Mega-cap technology | 28 | 35 | +| Semiconductors | 25 | 40 | +| Consumer staples | 18 | 22 | +| Financials / banks | 11 | 14 | +| Broad market (index) | 19 | 21 | + +## How to read the result + +- Fair value **well above** the current price ⇒ the stock looks **cheap** on this measure. +- Fair value **well below** the current price ⇒ the stock looks **expensive** on this measure. +- Within ~5% ⇒ roughly **fairly valued**. + +This is one crude lens. It ignores growth rates, balance-sheet strength, and cash flow, so never +present it as a recommendation. diff --git a/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/scripts/valuation_metrics.py b/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/scripts/valuation_metrics.py new file mode 100644 index 00000000000..896f6487354 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/scripts/valuation_metrics.py @@ -0,0 +1,49 @@ +# Valuation metrics script +# Computes a simple price-to-earnings (P/E) based fair-value estimate. +# +# fair_value = eps * target_pe +# pe = price / eps +# upside = (fair_value - price) / price +# +# Usage: +# python scripts/valuation_metrics.py --price 462.97 --eps 11.80 --target-pe 32 + +import argparse +import json + + +def main() -> None: + parser = argparse.ArgumentParser(description="Compute a P/E based fair-value estimate.") + parser.add_argument("--price", type=float, required=True, help="Current share price.") + parser.add_argument("--eps", type=float, required=True, help="Trailing earnings per share.") + parser.add_argument("--target-pe", type=float, required=True, help="Target P/E from the guide.") + args = parser.parse_args() + + if args.eps <= 0: + print(json.dumps({"error": "EPS must be positive to compute a P/E ratio."})) + return + + pe = args.price / args.eps + fair_value = args.eps * args.target_pe + upside = (fair_value - args.price) / args.price + + if upside > 0.05: + verdict = "looks cheap" + elif upside < -0.05: + verdict = "looks expensive" + else: + verdict = "roughly fairly valued" + + print(json.dumps({ + "price": round(args.price, 2), + "eps": round(args.eps, 2), + "target_pe": round(args.target_pe, 2), + "pe": round(pe, 2), + "fair_value": round(fair_value, 2), + "upside_pct": round(upside * 100, 1), + "verdict": verdict, + })) + + +if __name__ == "__main__": + main() diff --git a/python/samples/02-agents/harness/build_your_own_claw/subprocess_script_runner.py b/python/samples/02-agents/harness/build_your_own_claw/subprocess_script_runner.py new file mode 100644 index 00000000000..1f8764a72d4 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/subprocess_script_runner.py @@ -0,0 +1,77 @@ +# Copyright (c) Microsoft. All rights reserved. + +"""Sample subprocess-based skill script runner. +Executes file-based skill scripts as local Python subprocesses. +This is provided for demonstration purposes only. +""" + +from __future__ import annotations + +import subprocess +import sys + +# Uncomment this filter to suppress the experimental Skills warning before +# using the sample's Skills APIs. +# import warnings +# warnings.filterwarnings("ignore", message=r"\[SKILLS\].*", category=FutureWarning) +from pathlib import Path +from typing import Any + +from agent_framework import FileSkill, FileSkillScript + + +def subprocess_script_runner( + skill: FileSkill, script: FileSkillScript, args: dict[str, Any] | list[str] | None = None +) -> str: + """Run a skill script as a local Python subprocess. + Uses ``FileSkillScript.full_path`` as the script path, converts the + ``args`` to CLI arguments, and returns captured output. + Args: + skill: The file-based skill that owns the script. + script: The file-based script to run. + args: Optional arguments. A ``list[str]`` is forwarded as + positional CLI arguments. Passing a ``dict`` or any other + type raises :class:`TypeError` — file-based scripts expect + positional arguments as a JSON array of strings. + Returns: + The combined stdout/stderr output, or an error message. + Raises: + TypeError: If ``args`` is not a ``list[str]`` or ``None``, or if + any list element is not a string. + """ + script_path = Path(script.full_path) + if not script_path.is_file(): + return f"Error: Script file not found: {script_path}" + cmd = [sys.executable, str(script_path)] + if isinstance(args, list): + for item in args: + if not isinstance(item, str): + raise TypeError( + f"File-based skill scripts only accept string CLI arguments " + f"but received a {type(item).__name__}. " + f"All array elements must be strings." + ) + cmd.extend(args) + elif args is not None: + raise TypeError( + f"Expected a list of CLI arguments but received {type(args).__name__}. " + f"File-based skill scripts expect positional arguments as a list of strings." + ) + try: + result = subprocess.run( + cmd, + capture_output=True, + text=True, + timeout=30, + cwd=str(script_path.parent), + ) + output = result.stdout + if result.stderr: + output += f"\nStderr:\n{result.stderr}" + if result.returncode != 0: + output += f"\nScript exited with code {result.returncode}" + return output.strip() or "(no output)" + except subprocess.TimeoutExpired: + return f"Error: Script '{script.name}' timed out after 30 seconds." + except OSError as e: + return f"Error: Failed to execute script '{script.name}': {e}" diff --git a/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/2025-06-21_nvda.txt b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/2025-06-21_nvda.txt new file mode 100644 index 00000000000..6350a8f7d2a --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/2025-06-21_nvda.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-55AA44BB +Date: 2025-06-21 +Symbol: NVDA +Action: SELL +Quantity: 20 diff --git a/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/SPY sell.txt b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/SPY sell.txt new file mode 100644 index 00000000000..14305ca985c --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/SPY sell.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-77CC88DD +Date: 2024-05-08 +Symbol: SPY +Action: SELL +Quantity: 15 diff --git a/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/conf_AAPL.txt b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/conf_AAPL.txt new file mode 100644 index 00000000000..a4655401d92 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/conf_AAPL.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-9F8E7D6C +Date: 2024-11-03 +Symbol: AAPL +Action: BUY +Quantity: 75 diff --git a/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/copy of trade (3).txt b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/copy of trade (3).txt new file mode 100644 index 00000000000..28fb391fd59 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/copy of trade (3).txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-1234ABCD +Date: 2025-09-12 +Symbol: AMZN +Action: BUY +Quantity: 30 diff --git a/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/googl-jan.txt b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/googl-jan.txt new file mode 100644 index 00000000000..d8c0470002d --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/googl-jan.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-EE11FF22 +Date: 2025-01-30 +Symbol: GOOGL +Action: BUY +Quantity: 25 diff --git a/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/trade confirmation 1.txt b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/trade confirmation 1.txt new file mode 100644 index 00000000000..2d3f305d85b --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/trade confirmation 1.txt @@ -0,0 +1,6 @@ +TRADE CONFIRMATION +Confirmation: TRADE-A1B2C3D4 +Date: 2024-02-14 +Symbol: MSFT +Action: BUY +Quantity: 40 From 94d4379209eced02659fd0e981f5b57d82ee01ba Mon Sep 17 00:00:00 2001 From: westey <164392973+westey-m@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:33:34 +0000 Subject: [PATCH 2/4] Delete inadvertently added files --- dotnet/00-build-your-own-claw-overview.webp | Bin 38524 -> 0 bytes dotnet/01-meet-your-claw.webp | Bin 35778 -> 0 bytes dotnet/02-working-with-your-data-safely.webp | Bin 32908 -> 0 bytes 3 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 dotnet/00-build-your-own-claw-overview.webp delete mode 100644 dotnet/01-meet-your-claw.webp delete mode 100644 dotnet/02-working-with-your-data-safely.webp diff --git a/dotnet/00-build-your-own-claw-overview.webp b/dotnet/00-build-your-own-claw-overview.webp deleted file mode 100644 index a373eb9ed13f4181e364427fd7b7558c5b053703..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38524 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 Mxo>*~h;IM@0QVQ{xBvhE diff --git a/dotnet/01-meet-your-claw.webp b/dotnet/01-meet-your-claw.webp deleted file mode 100644 index 52e281d51c1dcec985236c013a69fd832aa0b675..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35778 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

&%>vj$!G{DB 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 WS_gRE&AcLt9s)P!ams}b$B+Qa^WrN2 diff --git a/dotnet/02-working-with-your-data-safely.webp b/dotnet/02-working-with-your-data-safely.webp deleted file mode 100644 index 2ab7edcb39d10f90025b96200279f11370d73218..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32908 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 Mu_T{B5ajnj0B`Yqy#N3J From e63571772c2de23ee13130b705053fdf8c7ece9d Mon Sep 17 00:00:00 2001 From: westey <164392973+westey-m@users.noreply.github.com> Date: Thu, 25 Jun 2026 17:13:51 +0000 Subject: [PATCH 3/4] Address PR feedback. --- .../FoundrySkills.cs | 33 ++++++++++++------- .../Program.cs | 6 +++- .../SubprocessScriptRunner.cs | 28 ++++++++++++---- .../valuation/scripts/valuation_metrics.py | 8 +++++ .../valuation/scripts/valuation_metrics.py | 8 +++++ .../build_your_own_claw/working/portfolio.csv | 7 ++++ 6 files changed, 70 insertions(+), 20 deletions(-) create mode 100644 python/samples/02-agents/harness/build_your_own_claw/working/portfolio.csv diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/FoundrySkills.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/FoundrySkills.cs index ff386850f14..aea7da4088f 100644 --- a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/FoundrySkills.cs +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/FoundrySkills.cs @@ -29,21 +29,30 @@ internal static class FoundrySkills InnerHandler = new HttpClientHandler(), }); - McpClient mcpClient = await McpClient.CreateAsync( - new HttpClientTransport( - new HttpClientTransportOptions - { - Endpoint = new Uri(toolboxMcpServerUrl), - Name = "foundry_toolbox", - TransportMode = HttpTransportMode.StreamableHttp, - AdditionalHeaders = new Dictionary + try + { + McpClient mcpClient = await McpClient.CreateAsync( + new HttpClientTransport( + new HttpClientTransportOptions { - ["Foundry-Features"] = "Toolboxes=V1Preview", + Endpoint = new Uri(toolboxMcpServerUrl), + Name = "foundry_toolbox", + TransportMode = HttpTransportMode.StreamableHttp, + AdditionalHeaders = new Dictionary + { + ["Foundry-Features"] = "Toolboxes=V1Preview", + }, }, - }, - httpClient)); + httpClient)); - return (mcpClient, httpClient); + return (mcpClient, httpClient); + } + catch + { + // The MCP client never took ownership of the HTTP client, so dispose it here. + httpClient.Dispose(); + throw; + } } private sealed class BearerTokenHandler(TokenCredential credential, string scope) : DelegatingHandler diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Program.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Program.cs index 0e705c83813..5b0d760984f 100644 --- a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Program.cs +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/Program.cs @@ -219,6 +219,10 @@ .. HarnessConsoleOptions.BuildObserversWithPlanning( finally { codeAct?.Dispose(); - toolboxMcpClient?.DisposeAsync().AsTask().GetAwaiter().GetResult(); + if (toolboxMcpClient is not null) + { + await toolboxMcpClient.DisposeAsync().ConfigureAwait(false); + } + toolboxHttpClient?.Dispose(); } diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/SubprocessScriptRunner.cs b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/SubprocessScriptRunner.cs index 39ac8d19e7f..ae4e29c53fd 100644 --- a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/SubprocessScriptRunner.cs +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/SubprocessScriptRunner.cs @@ -20,6 +20,9 @@ /// internal sealed class SubprocessScriptRunner { + ///

Maximum time a skill script is allowed to run before it is terminated. + private static readonly TimeSpan s_scriptTimeout = TimeSpan.FromSeconds(30); + private readonly ILogger _logger; /// @@ -55,7 +58,8 @@ public SubprocessScriptRunner(ILoggerFactory? loggerFactory = null) string extension = Path.GetExtension(script.FullPath); string? interpreter = extension switch { - ".py" => "python3", + // Windows Python installs commonly expose "python" rather than "python3". + ".py" => OperatingSystem.IsWindows() ? "python" : "python3", ".js" => "node", ".sh" => "bash", ".ps1" => "pwsh", @@ -103,6 +107,11 @@ public SubprocessScriptRunner(ILoggerFactory? loggerFactory = null) "File-based skill scripts expect positional arguments as a JSON array of strings."); } + // Bound the script's lifetime: cancel after a timeout, or when the caller cancels. + using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken); + timeoutCts.CancelAfter(s_scriptTimeout); + CancellationToken runToken = timeoutCts.Token; + Process? process = null; try { @@ -113,10 +122,10 @@ public SubprocessScriptRunner(ILoggerFactory? loggerFactory = null) return $"Error: Failed to start process for script '{script.Name}'."; } - Task outputTask = process.StandardOutput.ReadToEndAsync(cancellationToken); - Task errorTask = process.StandardError.ReadToEndAsync(cancellationToken); + Task outputTask = process.StandardOutput.ReadToEndAsync(runToken); + Task errorTask = process.StandardError.ReadToEndAsync(runToken); - await process.WaitForExitAsync(cancellationToken).ConfigureAwait(false); + await process.WaitForExitAsync(runToken).ConfigureAwait(false); string output = await outputTask.ConfigureAwait(false); string error = await errorTask.ConfigureAwait(false); @@ -154,14 +163,19 @@ public SubprocessScriptRunner(ILoggerFactory? loggerFactory = null) return result; } - catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested) + catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested) { - // Kill the process on cancellation to avoid leaving orphaned subprocesses. + // The timeout fired (the caller did not cancel). Kill the process and report a timeout. process?.Kill(entireProcessTree: true); - throw; + this._logger.LogError( + "Script '{ScriptName}' from skill '{SkillName}' timed out after {Timeout} seconds.", + script.Name, skill.Frontmatter.Name, s_scriptTimeout.TotalSeconds); + return $"Error: Script '{script.Name}' timed out after {s_scriptTimeout.TotalSeconds:0} seconds."; } catch (OperationCanceledException) { + // The caller cancelled: kill the process to avoid leaving orphaned subprocesses, then rethrow. + process?.Kill(entireProcessTree: true); throw; } catch (Exception ex) diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/scripts/valuation_metrics.py b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/scripts/valuation_metrics.py index 896f6487354..f91fbacdb70 100644 --- a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/scripts/valuation_metrics.py +++ b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/skills/valuation/scripts/valuation_metrics.py @@ -23,6 +23,14 @@ def main() -> None: print(json.dumps({"error": "EPS must be positive to compute a P/E ratio."})) return + if args.price <= 0: + print(json.dumps({"error": "Price must be positive to compute valuation metrics."})) + return + + if args.target_pe <= 0: + print(json.dumps({"error": "Target P/E must be positive."})) + return + pe = args.price / args.eps fair_value = args.eps * args.target_pe upside = (fair_value - args.price) / args.price diff --git a/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/scripts/valuation_metrics.py b/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/scripts/valuation_metrics.py index 896f6487354..f91fbacdb70 100644 --- a/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/scripts/valuation_metrics.py +++ b/python/samples/02-agents/harness/build_your_own_claw/skills/valuation/scripts/valuation_metrics.py @@ -23,6 +23,14 @@ def main() -> None: print(json.dumps({"error": "EPS must be positive to compute a P/E ratio."})) return + if args.price <= 0: + print(json.dumps({"error": "Price must be positive to compute valuation metrics."})) + return + + if args.target_pe <= 0: + print(json.dumps({"error": "Target P/E must be positive."})) + return + pe = args.price / args.eps fair_value = args.eps * args.target_pe upside = (fair_value - args.price) / args.price diff --git a/python/samples/02-agents/harness/build_your_own_claw/working/portfolio.csv b/python/samples/02-agents/harness/build_your_own_claw/working/portfolio.csv new file mode 100644 index 00000000000..d2e0fbad5e9 --- /dev/null +++ b/python/samples/02-agents/harness/build_your_own_claw/working/portfolio.csv @@ -0,0 +1,7 @@ +symbol,shares,cost_basis,purchase_date +MSFT,40,312.50,2023-02-14 +AAPL,75,168.20,2022-11-03 +NVDA,120,42.80,2021-06-21 +AMZN,30,142.10,2023-09-12 +GOOGL,25,128.45,2024-01-30 +SPY,60,418.90,2024-05-08 From 35d7ff0279c8d94a0c1658c3b838693450fe5195 Mon Sep 17 00:00:00 2001 From: westey <164392973+westey-m@users.noreply.github.com> Date: Fri, 26 Jun 2026 14:26:08 +0000 Subject: [PATCH 4/4] Rename files that are causing dotnet format failures --- .../confirmations/{copy of trade (3).txt => copy of trade 3.txt} | 0 .../confirmations/{copy of trade (3).txt => copy of trade 3.txt} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/{copy of trade (3).txt => copy of trade 3.txt} (100%) rename python/samples/02-agents/harness/build_your_own_claw/working/confirmations/{copy of trade (3).txt => copy of trade 3.txt} (100%) diff --git a/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/copy of trade (3).txt b/dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/copy of trade 3.txt similarity index 100% rename from dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/copy of trade (3).txt rename to dotnet/samples/02-agents/Harness/BuildYourOwnClaw/Claw_Step03_ScalingCapabilities/working/confirmations/copy of trade 3.txt diff --git a/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/copy of trade (3).txt b/python/samples/02-agents/harness/build_your_own_claw/working/confirmations/copy of trade 3.txt similarity index 100% rename from python/samples/02-agents/harness/build_your_own_claw/working/confirmations/copy of trade (3).txt rename to python/samples/02-agents/harness/build_your_own_claw/working/confirmations/copy of trade 3.txt