*j!s_ir4W*Ow7pgyf8(@ly8n~OIseI~6;jjs-LJy|EE$ z7V!h;Bu@@kEtM(GZC>t8hI<$(`=aCuvea!@U;AxFlSoE?U3w9>#2ps4ZV$i!JXH0G z(!9-0wb5*=@Z`&+9KXV~$x$G<<^4mZTFoypJlKU1z 9CEIto&Ug)-8C?p|6XJ>;i&L3`k_mg>OwR!zr T2Xzgo5-Dqg);Zt-9gmha*%^dXcr8gxv^i+dPn;$ug@tro=xfX75EB?L% zx_JU{bwfVOdAWQZ-NR3-l~F;f%N5eKAZ@wb)rce9n=84R&pN%hGw$@ob%3YBxye#D z`XElFo`oOQ55ybiohtJA_*{ET=eDam6SkSsmXfF#vnBRo3H4$z6!#m1^)BPS#L46+ zy-hXNcm9Hl5~?gemD{0m%|azzbrlLRPA`1x-axNgtfHIs_^m!%m8Wa-jGeZN429gR zk!1=MGDxz(@D4y9d{8OQ-&WG;yBbH8QHXq-X2h48q!W%Nv2+UoH ?O=y8$`L;9|SCUSW&_V(3WyP@6qkDf|J=ZcL^8X+ zZnBfWPTU_-V4 R&@uoM{bxSKkHIkZU@|}i|I;ED_Cucg@((3~ z%9(SSd*X<<8Ibk&7iS(^xT&t+tJn)R+h(2DROgb1SY1SD3)>2*WHBH%$m!@subVDb z$-NU%%uFmy48G{6`m8mWBAeaf=PTt>{xH8Xyo#aw#kgUcbeCF@z*L#K22k0S$r!B9 zf~9>}&lzhH(eh&t4sNNP=T$}ff&Amp5*e=Z@FCVmT!^fY`|8-`+o~&tL_Ja|z6wA< z2MrQ*?c@MIx+6H(8`-?$izxMP(CUs7N2yEJ?^97jXtyaS6QLzPd`SKBu+Rz7Mn-1t z;7UI1OYc9D_-OaDs9fh~(Ff5d{B)iVsmm}{8LnFCc>M$jZ2(MhLm&)xf6 R3_$dcO}~2>%j{&X#uP>x8{gIArCnI?KTxWlWfKPrc&$BECEV4}Cy#K)9Q=AZoUq zQ&&eX_wlELfzOh` ucu$XaMsjIdCdu6MAWG2wW$98c+wuJyhl-o#-> zKDeXA737_*g;45-2yU-49OYw6zRHNPL6+9)u1%OJQ}p1XIX~ 1icywn#$Iw-tG7Q2jL+vR=L(5y z& ga3|60n=%tz Md~Rq3-_XBp{t{#Lchlby)=BvsQXrr8 zXRZCb#G|3b1h}>`_aU<<=yWX&3_P$Ha2DIF5+iJ*snUIX!=I~f^{#|o?S73mx4Wcb z>c1-cv}jnOE g<>15#5kx#mY$$Z{3 vETZ^@?p)#IR8mCxeJ=9K%GpfurOZDPfShPbni zlIy1m`LCC9U2qbN#ITzlR8-(rtL=3LH#W zml(vDg;0~_)%)E8A$;9LYc)OYWqiRKE=-ZSG9w_WgU!I(7{mFGa1+w{vcZ=Q@>wub z+!|d5c>p_7_gbv?Q|zm~+4j6H1H<_TC0RH7V#3wFheO_$U*2~AA}X`cx3SVVsMF%n z_C_+zy~3wQcsFW4ewU9fs>m^9o)3`WT)M*rKak%IEqJ^G!tObgwjO8uPF!{kMtPcb zX=KE=6`@|}TsJ)!Io;w7(c>Vql91AZwogY#c4Sk(81Z_-ERqQ+V4^>cJlYFwLV+b4 zvM%UNl s z%veYH#>j8J?e>ky{~8MXLDmbfDcQ}qd Xmnu*z811QT<=Tb?yb^5c{C7XkF`)xBf+h0x$giWoJGjLUJvQ zAoGN6#7kts&{bS-m|85vAy|yeD*FRNlPv#eX$8KQ$xf+GsHDB*y@@USY3i!`?C|mz z;DU#d9P6@lO`2YD&glXimblO##;?N%R0&N-##-BPSVvy?O0ZW5olP0C7J}!RupAUz zBwT $!tzEcEdL %D~+FR0Z4`ol7S)x+#*aZjEUkrtT `+afP(Gwt*uUm)boD`@i1O%l zc_VlGK=*o|Tci0F2N15A3bq}+v;r_cv&A<+Xk*gtFbDUTmnb<}qa#Jl2#bv#Crs9Q zt1+us?HctU7G73O*O(6S`{L)B`EauPEMe#}_~>PE8eL+Q@Eh_y;Fbh4>I$h%%hv`! zv266N)j+7KwlPBr4(luNd6?BAN35 $9ycY~BN1okhy*4CuMez@P#tZ7_=TALl zroQfs3cXF0^Cr18r7*TR4GmAoN*HJx<3R8-^H$qyu*wIVtGo6z>&(0u6aJj7hNg>e zUTh{H?O^mRI{As-Wsq bILjQ|rC0<(wi-vMY3 z2t8t$Rqo^FB18o1*c4{F{a8UC!Qm1IdgLZ5VbmQQZMJSlWtgquia$veZC*k)**MsS zpS02y(+w@-=Up*G&~UH$OBV9fW;7BM9Pb{ k=HlpX>3CSIpo!Vjil-FOaFTwD4arw@Uu1x}97Y$6hl2|!Z5djWWbx?Ji zCQ$0q>NSL!FvYdF%u-k;PD)Hx$ZufRf0-^<8&k`VEe~+m?3i#n8XgpZ7jd}-QmCve zT!>+SmUnB97H@&XWyA{4-i8LF!Zw_S_#mXUY_7IAi3D^c{<3Aa2QOJLS`yyfr5snl z(-Ec)p;6QDfeUd^&;2o{5(wJ6=W61vUtf;e#!D8nNM?X*=oYYh|D?9P=CNx=OU);0 z&p{uuPuk*65|X1lmx`gRqNgXuNtK~zMDq&Dt}Qq*CYjmG0P|Ct)1uFQT^VCWB!o-a zby~T1nGEP@NG`R#6ZE@WS?r~%w3KM-A;>b5!C#0!JLIn-oxW|&jL{j2`SM*(lkqD< zERw*<+*^GS!cW>+l66DDpaWY;sKF7pg+^6@o7)Ow@g$H&Yk+yI>uGXAWBfT%`7(DI z&sc_ri3AlYvrrTV0OD(!nB{YOq<7{0rWC!PQULNiKOr$C7$pmE_&y*mQk}R^0WuV< z=zocE*(cDp!(kVBK*iAbKIQ9Kyw~)rA7$8mfFP^&{HV@ipY9}X%%Z}AjG%C# %+W(lPy#Rno&U9vc?jmrVAZ3dTtLC-f7n-6Cz5<^Ms7m(i^62*lNQNig>wX z|3>$5=h^*tJc`5Q)NSK#_PaNiX;LKUX!5Gq$ E<>#)YB30aT9QB+a0?k0-XZwl;iN9-GA!>#oN_z( zU a%%0rs!v*uj7$}!u*)5IDgXA}Zu}nr zr9fK0ZhUQVZm3PPo@B*=-n(*7VUOV%=sN!ZFDiq?v&%Zi8AZAT{Gj~72x2qGTrW>? zRyB_sT-#hlZtodBYZi0WesPif{{S;v&mn_JsG=5kIK{qg4@>b6j4rRVRY+jDha0CV zue7dNPD>1v(4WNgsk|EDFC>z7p6C&^RqmNKAY;cl *jFCEEsyK^X{gP8%6L^S!a|O=bOu6-m=pS1?)I=jYt^D_wHiOw}#j ztl&sxV$Ud>%uvU0IL;5uO8ej*L8;G*EwvVnmK~Q9=ges4U~&iriT)g)PhU#$yPp;d zZ!p5(%!*NlNL+@(`(rrt P$x;F9_p1ry5o+synbREg?3d(v z=ZN*IEhA3*A+lK`eB2O|5;$?UCq3{o3Gdq{Hf%gtm)c9Eu!_nQI|{MqXaj&r$;bfl zfH|)hyYX<=br7;my5153hGX**KTLqw@A8vbn#YV}wVq+-6qa(#s!v{e`*G9jM0jfI z(|3E{U&z1h&R2G{@;%|aZKubn%KPJyrA?a^$pvx;0Q4JF44#=i>mFYmTWPmflLDK} zN>#w*?cKCw9tS+*9c#d+@x=CW%<^2s0bS*{50SXa{W1^Nky!WN6IR~G&6asMQqh9I zanO^`(}ULrx23}=H>rx^88xPd(pH}lt*stLdBM7q0p<;yXXQM5j(TKd)^4ToE+w@| zBApWMBE%NKEO6Q9sL9*u)1`dKJ}EuMu^cf=A|jGD?j28G!{#SGn63}vm&T1xL!L1K zE@x*dV 2T@QQ=8cno- G0z8s$Q*V)_2jxHr+wo+N(a6rqb_3H>{X#< zATr<_a!x*x~}F+qf&aaCtL6 z-^RagtH3!_@XC!!5O!9(iof4u(V-}$zcUNr*X<3aYn~AcaV5Q;s~$|jzEaG1&If+P z^ZjdX>*9=lEWfj}h?|$dGWldHp~wfPOp<+i8u`cLsE@(kErROK&28=EB4)UavXYRw z;{^2>>yPSnG*5|k*0)-IqYJ8-q1`M otH*^416s-cNa1}*6|8PVQAk3V;RbyP{W?5KD{e=nm;N#p(W&|M{*%W zJfEGI;E%ij3P0dP_UFrVKiWP$W+^t9mQ_W^?*{zjWMp8HK;!BwBgOv!6K`*4jue{R zB7tN(M5S0U0I4VNCyw><)G~}r>Zr|H#T-IaTtGieUhS-EJwcj}^c{@hXdVBsJVJ5kMr(LvBYEno9MU<%< zgARHg`St0FiZ2`L)|V_BQh6e~eb(%!A#fMw&N=VcpO|&&Uh2s!>f #4%t*})=mPck# z7#RQ<<0A!0>6{#Qt&9CJXIU3f)eV9t&zTtKDt7H4oRUZ3(*$JKgy?=C@idxk<15IQ ziX;fL$W;N#oDMl85>MgHboxX(wfBbQeQITz;#CfcqjuxY2qbgclS;lvh_dFWthCc} zw+Y19oIbRq*XVjSi({f)MlFNhUCHH0QKeP#<5mE%Q_y|hG1HEjHN$HkvnPdaTT_}n zQu-TaL=xM@u Ql1{IyX)KV5A~|Pu5VZ5d(VLX0A~*dcrMP} zX48b?I10^|!jexd+dYm?CkxyP=q;=?ZC_a*+3#s#bsH+i_WMh?7#KNIg(EA+9PxrH z%Dgi+tKxk&IVGM{v@082ySB~0InGbfJ9_(8HPp8{9; w?9{J>5Xw_E-+k@X>F#Oc0I2`_#>vnGMM#kOYCuOGYPIsiQKy*a>sX5 z(C~K;N{v1M{65nzWs>D)k*+P?CY9%JGDR#wAOJ>A(aGln(-q~=c!yJx0AEs(gzgp2 za37tgp1lWtc 279~;0I!~zbkqYKOFx6_3>34n;zwPVp>nJ$6q{^U24Yu zr=j?BNbuK&Zf`ujIty5@^51Hf^zU)FxC83jc)-SevTN#|5z?md1b5Lzrb%n2#IP)H zCh;&kK~@A{^dRSh&j&pD#-*uT*$dmTBHSgk1IdV Zv|any!SHP zDlkPugnyBU?Va1O4+nxV>U|1X9alF$Z2a!u`Gp*7lS(ORuT3qf?OGMqpP~JxJvw+T zyzQn@0|>Ez2F?yx0yCTr-|b|tj(khvO?SeYrP3_-SVkz940fqt-1fj2BxIgX0*dq@ z!PO?Yp;0vYwW-%bj4`xh$xlV(?0S8K#=}6Cd8L+cjVGFtHXH%DRB_z5)C_$qt<$vl zd|J>rSx4GsSt3Rol|ft$-2lNS9-BvAmCyJKQnivBSmzGb`mNMsGb)vkOiBWM@~q$R zAaFP*uJ|Pc;`Yx{zw =Iju |UAMzixUd`)w z`kZY3BN_$V$vwzFC_sSZGcg%Hxfp)Fp5nE%OQ|)jP{PZ+#-?vC%M38ByoU7$ZZYaW z_NHHWI@?> (>o#@+cK^$XLcW%xnjCAYWMZm(@tPwd?`Mp+~Q zGVJPukM7_V4cwLkrUi4wu4t`Quk+Y+FDj`$wfr|QZMB9Pwb>E8Qh}10*&rY&DtnAz zdj9|qmML)!ee;&CqS;7prR?}WLnt#>Ah_aS* zoS)%7-8%7H9iPQ<9nI*TA@&_E(n; aYHI~hpWv8%tBIT`0F6!gg~3FtU(qOtF_PwflYMcI)ijUR9vXCF3m+paorN$b|K zwQm$&2Gi}98^x0I7gr^dafNXp3$%Z-Mh18!4CHaT+CArsmA=bq` axycXcx zTfl(-0HUD?2JXd_g$f2q5*%~}xaB%?ZFzr^9241Ya=O019;@Y<8VI2C7nO0oPu;dy zbS!zuW84mE)|IJw)_SWbCJ3X7*r~_LKvr$1gVf``32NQ(f5XihElKT6(fzYgkrpV5 zhC~ceH!y6Ff-(jUPsxrjb3j<>R$5inwY)EJ7n}Bz7bT-m@seAdmLqV$ ?3<^g80EDWJ*+6|T$0v?4E_KB4d5$Sx zGM5Gg3Q *ujFc`pTzVyi2P)+c%J7^yPkQW(>DoFE+c6% zv>@-ak(~D&@m#lvJ|YR%Y`OF0V(lD5az=XX&QCcV2XIF?tKKQKx3ja7@CZ%K)X%9q zKm>04v*oGkPE@JKe4Z=K{7-lP00{E`0HMs+Q6h(CMd29yqvmWJl20HKaC&$4u-IBv z9pH{merD7Qx_`ubtBclRJhJRrPR -KYOXSu4=ESMQ3SZs8Z>jfJ7=| zVgnMOdjaXw0=<9sPxwc1WvCraNuzxHnGyqmp19{5x$ZN8#c}@t2!0T^jdkdxT|LZ> z%I&%LEO30FsRR4`9P^SrRM*)501o~U>3SBC40f6=poUaav~Z`tLVulpkHP#sR+LsI zvesJbznA |xRYy%Sx+;s>1YvpBWyd|$aq>*_}A8W_7uFb4>4oA!N$>W|giu>cm)`t5@nl;jN z>seh1$d+bc2cQ7t^V+^<__^@H_8Z$|x{lQi^xHE5c#=Xv^4diy_#6)1I@jjhag$TV zP-@nFAD>V1^k$W5dssO2JcjQ``vuf`m8dHKMKY%13lwZ_RREAM%f?4vYLiOwBkNMl zF;bJO3?nxMvUwTphR>j_IBjRr^}}PRu~QymnidR9P4g4CILOWhag&kjT;GiEUf0Dd z<=aUVC^s`J5+uOdGoMx&IOsa?EAS?qr|jgdC8ykYv%B|RjU85jpi48EE@vNU*rG6U z4oK%dxyV2Mvt168;r%|}OO83(S>=WxSTV }yX%~uy)pEzO0%xztGA$|RmB}`?xm-A zZXdUW*%%6-JLChM!F}>`_#V~JcwfaM#20pRNI{NP^43)#ENt0Oc=aPc@E>aNj}ctz zz9at2xv -0TL8mUrV>$11rW%#ee!^5|a73#(W63C>Lz$B(W zkjLTgRCRxeb6wf!w$R5TM92Yg)PnAJA8g NrAs{{X}O7CdUfuRKOKTiVa&LlVm@l8?NkjDS1ga&yn!KZd>K zkkWiPqE0NKjw5W*I6rz^J21)WaEyZ_^v`a-^Wjf}5a~;+qRVe(5(bOPU{n_J LzJHyU?&O0ai zGau~Ak%XIS_G|8F@y%<*(`wT;ma)7sMy)K!TW;YR$aZ~B4^FwJ-e|Jwx^vuI;bOXx z3<$Xl%M@zO$3QtF*E#8m>89|UR(}!|-rTcXymKo^et#}jXxnpk!?=%*dLG<&dY^{$ z+lxDCBv^#1E@S{P7+|}cV4su{&4GYFtCl(xd3~IBGNT!57q9i9^WViwnY=S)a>}v~ zv!sSLVXzhl3JC4 br1_PM28JT#U1ocYk@(+b(eESI-d(#URDeDTWJK2Tq%`GDs*>sO)i zmDJWNaRsTkHt@tGNdmH?Nx8Cfkf30m*x;Ifhx~D;Xx<>XFo xFl8;aTZ+DhM(qLT2wUTd*9@i z-!l&X0L4}sQL?$XwJkN=5;eeN&PbDK@s-UZdKI-q$=Wr)qi(aq1E!hH)ISlmy$x z*pzR=@=I)9Iupp} Ir0UG#b+x*vvgi#g``t&$d+NZ(|W6lN+@sW`zTaxf1dXC4#aFA%=9 zt*xbv!!b)`xD7OcRSU=#OpN1l$XpEc>z>Efqu1|#C&S^bV#-*qE?lBr0De$5#;!?V zHlZ8X9zOGoan4xBT9l(3>8sbjPrlFQeEcOd3iC>X#$F pnR~hV2Y@URWI;(vvOtaLi^$40N zZSLll`60KAF_a9(n~pQzp~gcN B&znO8Kd=NQwAX>IGOZ}Bzdlp}Wg9#Qanz}Mav)xOble9}P$u)DaHRw#pWNOvl5 z3mlF~ ?kh6! zTw0hdkV*1ECh1W(5)Ui)iN-imIR_Q(o&h?3i=b-WDv?rqONgFW!=NfHODb}D@TeO+ z1CTiZg*?kKsNc1yz3r|401a*b07Ggtr%@?A62JBMA3A&|xx60}E_EA=OE`3UDCUZ3 zOYV8*a$z#EmgjWwM#FlYss8B)dh_8{tE2oq@txP1Zyu?txU{tf7XJW5irOh>QWuey zXjFrY4Y})qUg7Z1_I>c@hCUZhd9O` pThLpepjcizL!V0 zgu*orYPw!B+s^C$82N8a_(5@f@k8vQ@^F)A4+oPw2ik(>-6w7^3CUr=86;KvFWF|+ z_xpNHHqOG`wF_^s*}cZqfF!O zHfh?i+ k9KrM`_H6;0snGVUuY)Gcuxjlj0ucKeseB=YL1 zw1OEpI0JS!1CU+tr$fBbJb!T%Qb{eGZ7O;DalP6#l?dmIbH+d&a5x8`__1wq;_nkY zFzGk8S`CcRt)RDGH6UPB5i-9kIVWiwi{zFg0|N)ZM^^Cuy=Wv$%|rbt!FMH`W9*jE zuKloiz?5R4z#&1&87^>Z>D2KRsL9KAw%^b1TJ7C>pED>_a(2^GJH?*`wGSD1<41E9 z{F2>X#AQh1L?|9iWVr;h1DyP$jB*ZZsJ8IBH;W{{lHtXcp== amCH=ree2ab$;;Kh7&uTGnKHTQpCk#UTYaeJdrSnw5| zk*DZeZQkAWN#1!9X*U8D(f4iINN4j8T=YFTu3uEMlU&lSufUQfywoF|o5& GJ+TkbF8&7$5$-EQ{vP!PsF4WHBfXoRB4@_5` zUHF4p)UWi&VwO1d1c )eVbreY#u)N&bG1PO zKX~-0d{g37@gIn+v^KjRWr3iA>fkUY-Z2`70~{^_md~pm*{?hJvEo}>JIzK*No=h| z*E@ fI6OByk2lNa%%dkHjQ;>1YXZ{d)(!B>G>ji1u_XL2 z%mL?a0qc=~J;B29UYBoo;7h5kKYxF(O!m=4u_!k2p$17?00YYb+mPqdw*DI4HnFN| zTCM!nbH{56tWXtKmRTfVt0NwvS0#uady}5ke?;&+$#G$9s|2@ZB+RisV@2G~#IYWa zgPeBbn)(WIjSV}0U*vRCYM!j-ei?XHO<%&caLqK WV;LmpDtXS`pz(rF zU1h8dS6wzywa~P-g^Ro@NMg7uHy)YEI2k8_ft(J9!`f6b&;6UGz>9Nm&AvccqD9^N z!ghdg3LX!r^}+T30D`^-u< +T$J21e zQ1e_&u@$t8cJ==NfxA2Ku=cZcX0+-4XLI{Cd^np&(S(xEBvZTY*kmD9P71C8>@nA= z$?snMqu5S{HCdqrR0R(tVE$!APvA>CZ5rALBGcvaq8MDukUjEbuHM602?;-7m^1PK zx$D#Zn)+AmSbRKb!6x-RHKxetEp#nK+?5uMCNfcOAkWjMTDhnAQ&GB9Eet9M`>Qk` zpB2=upk#?z?PgSAgZ`JC55jIKE$(8L+C8rnd=6x0e%%QBKp&kGQ0o5x6IiEXn7i;| zAu-5Tc*8K*t^ho9!LK&>+3>GP@g9LPPknTZxn+1siICuq8zUWi8uu@>tM3hSYQT&K z5s~;0-mtD~#%&&>rbwZDhw^+I_>pprV)qtk zMdgIE0p(mq@;kgI1364!`l(KNujh_B$bF6@>-cLmqLsV!e?1fPIdg0plzy>K=5Shn zgC@}YMQ&}~Zb%IYc5;M *7w_`0B zB;e<9KAdoQ73j7$w*Dl!vzpL(G2En*LmL)(BXx|*0+KlyUY$7^t8#c}QShgMbv-`9 zHn>RUNNx-OF_DWaF B?ZXV;IDdnG+e{a=FMS zfuE&t@ 55uD@CluW@EQ` z#MajhAqw+Nh77=xdPt~qk@EE8f#^23Hog NyKjK3on+? z#8O5W&g>aS80YE7xkbft^DiTkHCs+G+{W?U+}66~(H6H>yV^KnR2%%g@uNEvlbqx( zdS$+q &Q7PDdOH_U#(R_FHf5L2hm=mN!`3 zJ`b77g3J6QvuR?5B$-UJ5IF>Lq0g^Bg?bpAW5mMTsV%>+yySATR{p=OPRjQ8 zPPrF43Z=A`u*il3F9vbtA F{E-`+n= 8azBk%=pPICiVL3x>$-N9wkA^%({%V-WN$0S36RKGg)$J4vfv)A#(LL7@b~t7 zyV7-;Z?z(q*1ut%Xd<>REzYGIzUF2>Du!Z4Gv8<&DRt^J{{Ri?7k)m_;(Z|7Sm}Oc z#mv@hhT7fag5j7F>Q3(=U|jcSP@sh>I`a(9jv~D5wBGA&H~g)qSKQ~77NxJt_5FV{ zjlZ_>F00}V2f~p^kVzh$1lpy Qa7!n^gGNcfC;{fFPM}U3?S$t3gy ?vTV}#rZqLSD=&K=lfYz={d({T04<@^I~_mVuCj;lVV zkeh2rq>+rVKys{hhR-MFVo4iSPB0HWABy}-tJvz+FlqC_t3AcH*aVzmSOVY?*CqCz z_y}?cCqF-$W={~+J+!~w*YP!{QW2#Y)LMUA`rGkWI(=uudQ|q8Iyk$xx3kr>_C=Y< zi_Dql49>BSnUC(HJF~{lNg!vQ_>XrNhJF(1Ha6EVy`|>5?<>y ;SiK`>CQ`^+qO&M}Y)89DMWl zAbjs+W>3=^~+tMY&wEHc?7jgJ@WKiXPb*<3{wu^U)M z3|V9>RKCeLQVx0y2EzXUc!A}<6c&r)TOn^GMtPx>u?%q&5{$ ~l#q&zn`7g-Q7__Om z)!O#5>-hZ2J}U6#w0bqo)U6%e!Y`8mRNWP@RtkPz7?vTpZ wX176rqSV&cqNdS!FgFx6#|{C%C4+Q$s1Rk zjMv*`v#E%~^G05lx1zVtt@Z4AxcY95enqXG_U-zf+oRZNdfv5lVS6<3T&Ab?)pXd6 z6w_$tVL1xRZrp^OEdx3W~ Rt9Pm%g+If6)28FKK-br&RTH5)J zkvYs}IM67_9Woux(!rRy$T&FB VkTht4na+9n)ck|*6=vPFPIxaG_`cf5!lKhoh}zkuf@#`u*co7k5xPmr zo*9^y$;YM%$ra~+5PmVu;yLBIf?K~gkj7|R5uub4n}^Ck!TC!Mx(?nenY{6}r;9Fb zY{lKl8hMTYH*Jz5`?q#t9P)4rdk#ADS$<1Wlf3rc%gyiS)8&5W46##<(%8T8TgR5` z_K|NS(dq^$qH%QPoeHjGB=NBnMo8RpaK|_#*NvydNVWd}?QK%fL~UX-I1H_cau{q} z@ RXr(lePDqauNyn*d~z+2~rhYl-b(@O#}o zq?6dS-<)HHMlB>M9@P(?Ig!ZD0O3jbl#2Vz4qTy4D|Y_B$f!b6_pSY0>Lb0=EcAQ5 zZqZr`i`&BylHo(W;My6&p#Uxh(oRkUgbeocuO9q2*MH#-xbaQoLdagipJZuQdi;_3 zvNjJG1Q1B)a6EBcgi>l>6y$;nZTdEoVP$N;XSaiL+p4sUHd8+_^PW?Za!h#6GgA1o z;)D3F;r*&>B0NQ@-OUB02h3%+NRbi{>z|pG3KDX60g=uRu}(6jB;vJgU%Fim>QGBm zdH(?H+2FN@ReAMm%ak|vsVf7LCL=7tTRA+C2LN&gbDH&gZ9Q~y=w &M@^j}gAMvJ6ccy~y!xzuk`DWid=B`}Er`>cgG9k|*~7lF7}(0{St!tEo) z+9CLr;+SP!3&XL?CY>bX%LH;{xx(WZBG^UF265B zE5Tn2E eh;5a@cdJyowTiV zOzkXb{=JyxpYbO@jd_Q|WN(O`G`;aw29;~5!Y%DBZmy9Y*4XZ28v;(&+~+$ocp3Kk zXTUmj+`3#!lO?<{F2pe8#)<|28AanAfXBUl 2M%M`4aU!I-r+3UEd%aY~W z9Xj@P5vG$4KI?y@?#Hh=^sT7$T|uE9UX5-O7%Ep8`~sT0rdUkCldBMlG0bFh-#mRQ zTFXWfs)g0zW6>)4VBmYH~bR@9T!}R07ipg%7C(vImf z0-`pXWdq<2ZIQFb)C$y_!%QNO4NezlQ-JZZgXz#!xx5Vtg<5;7U^CAzocnQEaz~~9 z^HnEpPI5gvU7sl;=_srZK2j(@`1!?VYq}1owvJkBAh8lymQo1Ag}DJ-sWV)Vwus zcNq~it1@IWi@8G&s3-YXC*w~G#x(P=?r<^zydV-dJns5?*FAWySIc(&O{072cz?%T z3A{<6${SRP00cUucmQM6At(Iwu2;pHG@l=TXPc{du3uO2e}u599?(`*MLP#Q45@*h z?t>!>TE7x}8E|HuXSt5*(_uS4(7V*+^N>bHI}!NTm1(*)=Y~9CcI*A44x6Z1rK3D9 z?HqCk202Oe8DRM*3d~1J{O>iuO1zq@9Veu $Xu_>JHXR zG?B0cHy8+Qk|8+Y@IlEO6Oq_^oEs)NVASk_V1?ZrquXT1ed6K1$~qTsa;7QaP^_ z@ibPN7mRQ3;JyOGS#5^aB6ir_h|ifDjmK`|k~am(-COz(j^xv3HqSovx}WS(0&vI7 zRmnLx-S=^mjFHyAo%oL@tAoc%f?IvfJ8R~A%|!6^94vMJ02RDJZT|oZFG<$4`=J_X zfm-(66l4{Pf t~kZUc}{9laOWSIvG8__2SW z>pEmMGeMc2Sa<9ykt&BQcmx5wat|LN?bp)g@gr(>FkR|b&{-|E5uq%yNE_x>007JK z ~)6yaq!c+<3x}272IjB>iiVwecK!B=Nn}XHlBvRT@TQRE0?cb7wgN zVK~oHKqon`Nbnx1{{RU#oh6BhZ7mi#?XBmJt2vq{XWT|zu l@xdg8tbnkZc8?t(HRy-4X7msYU8JJ&NGQuT~ z_kw6b##u@Yst)ap#~I;HeJhjk3yW1X>edj&dU8}WN1Vh6H&zZttu>(0B zYp(sBJW(f#ylFm#Xg +7O=9NE4H;ywe0@@ zU-)CM4~Ltmmwi2Y1nD+`q|a=Sl(N>0HsK{8EQ=@wayM`iRde){9qX9*Q{cldiY&{P zjcp8%BFP|m83HkHl=2W@sqQjQ*VleC_&N(q%{?q_?loy*xwVQIRey6bNSmO2!Aord zJh8%n@*aJ2v=0kicq>uyHmf9e7STs%9E__OQv*&Sn`l+TkPg+x SzR5lrg0VHk79V^FvEJ1yzT4}azrpte;eX=;k%IV@ 7A@w1uygYRo!uPgnkyRLQ}Gl0N7Ccg9nr2KZN~Q8tN;{t2!&W+i~>pf$DrdN ztHoCK4l$^%+P;p JUymB`nI=eYj>whCGFf1pE60Le1_cWF}sih zDEV?mc*SQ)u4y{V7WdQZZ62wpDVp6{Hdx_}$R<)Tg2e4&%sCC7Fqr4>tn|%G;yUR% zeeAb0?E7uxFhr{bsgaei#rZy5UohT2UBiM~k39H`@e@k$)|0AhH`f;t%Pqu_*$*%o zr4c91A Q4*L<4eT*3&(REm82~m76{rwg?1+ khnPV*C!_&5AN5|9v1k|VW#-sPZxLgcG`BCcRh`lk_*i&(|wtD z@NvL-asAQL9M_YWWFF3HP>tl1(RaPJ>#o60PIFXh%E|tgOJD1u>|YSPWe3A=gSXm+ z)x@i*lLJ_!ZmlV4N0|=qmzMqPWSkF}_g*W2)c!DP7ak ct zbe n>v%kqEa)6n3 4ScGJVr+G=D+s7m*Xz2z?&q v+tk`PiO!trO<%j~ch~fO zr=RLtZ CDo>lE%fse zc^_(xu2kjQ$Y50LBLEOvsOSg=x$R5g?yIQ$T+^hIb8Vq`Vo$OoJ{fg4RSXzlf_`|| zpHk!uWr*)QfACh{OI
y!jp_b`2D2%@YPHyJTOx5}Xh~uU`>T zljTYDzMVDwRlPqhT9bve)aHB@b9X0-EL_-6d8O$hTiZBg%SU+PJ@E+~03Bqw2RR)X zMn@v6Us~I0zButErMv0cg6X DDLlm>H_D|6$j>UEXOcY%_d&ANb?qYJSmL<4v9#LQU4hKsy_t_2 zfFv;kIr+H*HO%XmI@YnN={9yI-u^kRAdEt>sryio @_FLHR*FM;T!2)RjdT zJ@>y|(KudaRpJbNqIXlB%i!%-~Rw< zPl$dW(RFP<;d0AsYo%#0!#(tNkQjuDp#7fLJ4)kng55Ln05OqWwv;q~*su0(32k|4 zsCb`LAtCdTq8gR_g8;J `4tg f zXHhH0s~|Y}hs;g^;DA3PUq$#&OYm&AG0NJulKX%p#_5CWjMpFGkAxl`J|VSud|{_~ zkt(l}RnME(kM)7Of-pxQcE~=fW$@Icg2pwwXrd>k`P5^-{I@-EkH)`1%doX!Pm`W9 zx0?R|HTfKr-L#ee03Y%t({wKetZJ*M#?tj~CP2Uw$pZtPwY{czGsBmSnC~Z;CmX!L zj6XxgW5Mv`JChc -^1= zi+z6Q{zpx7;B69kh+RtLFGf$cg&E!Ju>Sxr#-q6KXNRq=fR9p)P0$%NJdelZ6~$`C z^G%6Ny0CQxcQKXt1cBb{eSZq6d8xw$3p03<*92fBlDhZngLo@92D&f5{t2vY=l2_$ z&x24(rY&zsX#0VA7~A+C@D+otcrqkikZM*hD{xoLfagA)`u_m>>MP$DT0#4{d_$zL zWgqg~kPb6~e%fmrQTT~wp`(vq(gQd5E*+1rQFof>n@M#0{{Y~d#xKm`J|g%dP_$_h z8Lg4qDz5%P2h*N^op`5>JPD{-O(NXg+cM-ki*31lADK?o=Oc`J*S+}9$F{=M=J!vy zj~Lvu%Z47~&prKX%e-ZKYvLJvn59`G+%PSJgZPsn=ReB4JY@wvn!nz5QqxwCJJvi6 zZ}AS>P)jMihFI3t=1jYJa)tfOs-S$$+~gCGdo_6Wt8J|4x6ZfXD=k;;2^z*C<|kPr zjY^Z$XABQ;M@seWUs#L4^IX^jku3GeR^IvMjbacELe8$FjnTf+bDXF>PAkWLAnRK8 ztFB6Q6;D4)Eo-SqaM@rZ+|kOU0!oJY8-hTQSbfU;-;45Ztl|B-w>>TUxc>ma{{S e4x#}UOX&9t`rSAOM)v*3aNQl$MyOjmQD=s)p4GMJ!dxR_r^ z3vTmO_Gfkn%IC}+dM~|kT3?B$zS07#<`_f36+-7bk$}lw2h0aK1Pt@VYw4ajd3<{Y zog6b5?Bk3~bCApeXWX{f!u?eB>VF8U?PczNE&lBfhpj$YdNa;^Mc|!X{9SIA4DPn~ zH#1Hmh_G$aJE+M#0@7~iN6U)5b=#i`_ WQ#0(w-DI{}(F<$iw>ZdBJvfcde{d|p~U*5cqheYu_8o!2gndGy* zxsDh@#Iq^iCA-K*81flbPE>=Puhd{?=uJz zJitls?54agOz`cNnW$>l*AIQ=TWOXzdSgOI*|iYy!m^-5Kp$$m;Z6=?Ag@Z6%U_>Z z@gIlpE+m|_-R;e(`$PP;>hm#GZ$ejoF^&lQJdD!^3e&n?>c6Ghzx+R~j+xYyTW_)J z`o@#tkBHtL*K~KemTwV5r8V 3mLRJWo<(>H_~!TFkL?>izCW_1I-F8pL7e7mP;gO? z8!+V*jAxcTF`q!XgG|z)7Q%S#;PBk;k~|0fBI8V%cU!jN`SU(Q7|RpBB6}M1B`TC@ zs(Z#sKSygczI>^5yFP<1$HJ24sRY{l_T4?Mp1W^j=?hO2!L0Z~`E`55j!0v9j4V}V zxPSu@AUHVM$Qek_&77{<;q}d1S@BJ*O>?IR?5<>VYX#biEKM9 0C zXU%nwjQ4&m@ibp%3}l|?%CKv7SmH1sj1*!rLaU?T<&IPg9)s8XPo~*;E5kaBPjvIm zbc-d0yikcJiZILpUJ;qwa}UF@$*-8jDbVCoUi6-eT{>y$roLYzyA_yyVw_X^I=9~K zzguc;S?k^w(|l1LhZou5)-EmNfo2UPXm>ZxrHe9SaT(o? 0HjM~GM5krn6XwyJ4sdt8+ia{(>#BRp|kKukF0gQLUfN$xU&$+B!Q%sAsdE& zkxBWmhZ)XTC>;%UzYhK)L#g=o*I1KV`&Es>`&W__7c7id_m8{F3*{2TG3RUGHvn`` z4Jr^-la#KLzP4>Ww)N_)a!(T)mV;KdnpTFiNs-%N=&Fi;gIpe zMn_y^u9#yfRf?3X{aev?>-~M_qOjED+@&{uw!Zyd$ISl#9eygy;Qs&=>X7JHc5kE2 zaJC{%Iojgp?%_yg-yjSK@@>kEuE%PIZ QvX+Ue}F zE5mGv*+;~!^PWK5*xbqHA5_=vJRR`Q;Qh=`Wqt7rSJQ*oO{-c?EHwLhW<-a}wO|@q zh-Hl$L{wqB?*qQRTk%$az8~=|{*eZW6{fLgh5o}1>jsjs63q89NaW>P1@|yOcsN{V z>oRP ~ZDGAuJx=;X%(6(wg+n2k*^YRSWr+mWRq#gC_>;lus`!#^Hs4X#wM&J03{1;m zquP1W0x&^EV*zrV7$On#5nPU!@X9X}{64zzKB0g8rKhrgWm_eqNeovfA!S5zLou0z zizKQ5jtgtd5*!oUe%ZIzUI6` i4Y%w{@e9Lsv3B`^`$^xR^jm&zEf!j!U~^d+b#V zA}qRNrl{16F!5V*rM}6w`}O(n)wSo+pzFEfX1&;N(*B;V{{W@kk<56z#4!9c@nlx^ zH&a|oAK6wZW l;yPQN-?VS>*mt` z05^a52;-*}S*1NU(S7LkPlG-Q*0isI{w{l2E;ij>%M_B!!pVtk$Y4qNmoKn-htGPz z@rR2czl%^?Th+8p9^oaPG$bK}Fipp)$YU3Coz2@A={^wrSch8uo$jN!W@TkeJH!*o z2kgY=H6uB2p;T}_na7O$MbfS`{X)xDxSh27Ul3_?tJ^zen`^kq 4 jml3y^B6BNCxm$upQ4hY* zdf?Yh@ay7z=t<@Ip||tOv;{`#wg9SBW97jv?0aM$0T}S>7P*e{YnE|oVLC0acZtku zzDmZW6lI&M^cc#VoY!}x>$*OZplSLAt;VS%UM?;tkeJTE0_`9d3R$>j7$<>@oE &Kow*YvBYwHtdoyEoKh^ASuiOA(IV6^i5yxWG(;gl&*youeLWp?Hqw`^OVpPh$?3 zXDqiKRqXM{G^iy9pE0u0uyUlLg*#X1YuWx2_^mDc6?v}S-bEx*pi-czhE!=?;{Xg` z6A~dFkBsn5cvVxOWS2#MU+enR=bf!(y|nfIzarP{;h^bF;m;7otiXZ`JBwHnNngnG zgmbi#Ha7u*xZ`&Pim~g8o>7vrj*Wh1pNXv^ z@Q3z3i*Mw~uUKi)S(}+vw(oQqTp+;$RfnAN3lW?yIQ?5fw(v#LhnC1qi5AvaHwfU3 z-IoR;xsis?EDQ!a&JROJjyz?k>)tWAx6{!5w%j$UOwq5IY|hZ2%Mpax8Y$%DIVZWz z{{ReVxB88|vg+ZjE# hXemZH!r5GnSzU$ZY)Ycr(S8T4n zA&=qqpKo#IL2m+yzt+gaAl^)^AKlJZEn^m?=>5B zn#MT^4QmSq0ruqJu-%VD=ss>d&-Qcuoa}#UPaZO}NiKomdEuJ!DJ|YBOSbaaR^N6G z?idCD9svY`MSV;0!%&;V{tnc<9i=t3rlG6aeUun33de4kW#O<0z+ifMbDI0E7s?ux zYsxLoZ%h7c`;3b%rx?6dRMovtF`ce|X}^wb;$bbUo*K|IWunGpBg|~#OM}KfW5SS6 z$}%yy*U>%(@SN8AdheFX*<0^!zd%MmKDEO95B;8X4+v;BI&5j85pNJw#oWkL0geih zfnK|yd^6W=A`fo1ib&cSH3oD40FSvf`<`Ecl?qBKKE9^-n%>rKQf8ivZR}ML>N-4S zSA+JjcMS4!P}Zb+^Z>}xYkDrl0aSgiJbItt =;Szt1OjO~`(pRRX`^iry}kLGhI!@u?S7WF@fns%5u*R&YU(lEDik)Kby zRblbfg~i6?@g9&o!TdLn{<%X=ZwPq0AU4>}Hu1YKl7I3gLvi818N~}Uc2l=Q X#W5bpNe#=c`QIy z(`0Cg7)?Q>=r}wK=NSC!gYg%Kjm4CTERx|iX99U$LwCmI$KY{W-YoI{t#7M@eLm>I z50@}Hh9gtJ1Q7gkKs@8-6@lXqh!1b3>~#D7l%)9Hg;Pl$XQ14kC2c5SX?vb1Y$NoSKDXaRyd zZQYZz VU4;yPXx|{|xHJmRi2?U7K6B`4=eaw1}r}3{h)_g%{CcE|<#Zd*y z`8N%)tZygqk_gTL!0E;tv9HazgEp2DOWo$?+g_U9>&x_IR>jH@T3tPl7?Z}A9t-%n zH-+^LEp2R|xr^+QNat+Ox-eP6`AIodh=GzAg&Yx{s@%Va{7+=}Qna^AJ4x~k1H3y( z J~>={8;{(-U8k((Y|f!uJOC;qrvbCAzY+fyg-u1d4IDC;-mt=e!em z-xD LXf;s>x_wF^j^B@9W5Fj<(U&ZLqPKFU6oFT~Sh3mqnT1J4DNaZCwN zVKQZp9A|neu08NElbhNGsRx5^=P?+kD5b9VMxsbI4ax}|5J>~K-p@6|d`8yc*M2wa zLdMkGOL=i;9A-&OL6sqoFZWN%rBrS>11FmKTr_1;tYI6ZmG9=PzgBn=T+Z?7`IfA; zNVP8j>N 2_|{_L_P}6mmuuXzmot CH-+nMMa4-o3 z;;2un_?N^U3Go%}j@uaKyRx*3>Na^=WN7Eh7L)E` ijL zr1@_yuOvd|+C{f*!ZZWsJDh;L0%SNNk~X{x uc}O(KA*%*@XFq-M$x##IS`bDZM0zC7w;{{Z36n|L(MTU5Sy(mP!y#n}UvD(dn~ zMoel$IdT2wAg= zebW|L#H1> lLuA|1&T`@y%E>HJx5|EPtCkFVkO$tcpT^)EYE#B z{SK;iT8r#*-?XL1xvJ>;MgFI$$z^;ZFpFI}2Dy$h3`LqXKxAQ(!zADXj` SoqMqu1 zEdVF1!Z%nuNZn})I-A#YuJ1DH)DWu$0fkZ`Y4(}{S1mI_k zE=cUn=~BbtDbZ5B+ge+?dU`AB_1~$jEoY lpxsLwkdw|e2)v|et(upNf`*0Mh3xEK? z#EaaKMSLTxPLuX9inMg=_x#VSqnRkvin81K?s!k^r8EBkZ)ostZz9jbT3NS`KO_Xh zl2mkDpGx@S_KKb0@F#)U9g(%2LsFYiDsXR|8c?k-{Pbn)TO?6MezB2%$j+y#{ZE+3 ze-Gy`{U!&n#!Mdve`i}1J1nlX{W)g0ULu%1%!R`*L%8yCIqy|}Zu#C%ix ByR5zue{j0B-*P=_fn!g4QSfr+yXK z7~?h~>q>EKRCz(3;nmLGnPo%-H)3; z 7w~|DNyOuG9je>>GKs#fl zeH-FK_CJRgaYOs4*2=&HPnAGeu8QzI2n2c>D6c0S{7C-*i5z&ZjelK+c+XV2gWxsv zsdG9?n#P$Ly2wK+x0AU+^f@^l^HX?57VpJ6Ig|+u@yH}DGv)@G^;jJB$W;eDKpvD) zT(oxk{{SRReh-)V4ASl-7fm2{4=;yrE}gd=yxGT?Pj|orcU}c#&v`eS;i2Zqg|&uN z8;=f5V7J! tY`dx>$4sc_`lbg_fPB#V+NJ`B+hMNirBf-Wp610ZgD)|F~@Kf zKs|5=rFgH4FQ&TvsXSL4vr8m)w PEA^ba__Y53z>m}A{{SNB z{{Y*+lRk;iY~hbjLa|1qfszyq@IS=YSK-@u<%xGjjrCA_QAK`@gZ> 2x#DK^KJ-yeuIEiJh~lrjXRLp21^(95wuuPG z+MgJ}_pXl1#TuL14cd+I$>%o@&p%oytd~=xsv$bv?3eaMuP&J4PO`D|_pJ*ZUhVEk zH&+B_p^*ChXrh!#UkTDkp{*Ur1-*OrsIAm}xdsLgQR_t&Q#qr#jjF 1?Wss?uK) z0Khnq;-S5PBD!*jigI}a9q6LGtUvpmKk%X`{0QJaAV|w+a>1B3$6V)}Z9G?n`0jT) z#J@XyvPcI#2Ghk9SL0dd{EQ*%`V}vNKjQrlOZZJAU3gPS^I4?dV`|N~=W+4}CpF-I zvre0DqThJl+Rg}VE#UE$@<$XXBS_RnKmZN^9@J4@haG>&o?rIw 96`7r{4AIdivK>s@ukXDaZS?`Igi-$~gi>13yd;$WcXpH80|PpZ?l> zeD{CXVjtO7(ks6c&ho_^j~IlbI)*Au rZy$6cfXJu$@;S9K5f>3XlqN3_3%FY$lvtf!+&&GGKuBFtiy;8#L^R|Z*f2=8A& z`0h2+JU`-ewoz`8=#$8c5ZD!#E7Ghn(1NN#>{NPDMRI3f9WO=t9TdJ7{{U{DH{ttu z?~a_4qD-^JeDa4-!a}jY6t;ShI2q_G+5R2M>!SD~V9X^t9f2+n%t?R~&t6C$l@wP# zbNmSU%km~44E=voweh92bNIi))~^~ptZO4AETG1uGLS;_1XJu`O+rm0?FzH*)YP9a zZpm0JiuLp$5$S *~D3{_5c6? literal 0 HcmV?d00001 diff --git a/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/FoundryAgentsRAPI_Step11_AsFunctionTool.csproj b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/FoundryAgentsRAPI_Step11_AsFunctionTool.csproj new file mode 100644 index 0000000000..5e73fd236a --- /dev/null +++ b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/FoundryAgentsRAPI_Step11_AsFunctionTool.csproj @@ -0,0 +1,15 @@ + + + diff --git a/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/Program.cs b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/Program.cs new file mode 100644 index 0000000000..ebfd7e9346 --- /dev/null +++ b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/Program.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample shows how to use one agent as a function tool for another agent using the Responses API directly. + +using System.ComponentModel; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.AzureAI; +using Microsoft.Extensions.AI; + +[Description("Get the weather for a given location.")] +static string GetWeather([Description("The location to get the weather for.")] string location) + => $"The weather in {location} is cloudy with a high of 15°C."; + +// Create the weather agent with function tools using environment variable auto-discovery. +// AZURE_AI_PROJECT_ENDPOINT - The Azure AI Foundry project endpoint URL. +// AZURE_AI_MODEL_DEPLOYMENT_NAME - The model deployment name to use. +AITool weatherTool = AIFunctionFactory.Create(GetWeather); +FoundryAgentClient weatherAgent = new( + instructions: "You answer questions about the weather.", + name: "WeatherAgent", + tools: [weatherTool]); + +// Create the main agent, and provide the weather agent as a function tool. +FoundryAgentClient agent = new( + instructions: "You are a helpful assistant who responds in French.", + name: "MainAgent", + tools: [weatherAgent.AsAIFunction()]); + +// Invoke the agent and output the text result. +AgentSession session = await agent.CreateSessionAsync(); +Console.WriteLine(await agent.RunAsync("What is the weather like in Amsterdam?", session)); diff --git a/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/README.md b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/README.md new file mode 100644 index 0000000000..ee18e9e6d4 --- /dev/null +++ b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step11_AsFunctionTool/README.md @@ -0,0 +1,30 @@ +# Agent as a Function Tool with the Responses API + +This sample demonstrates how to use one agent as a function tool for another agent. + +## What this sample demonstrates + +- Creating a specialized agent (weather) with function tools +- Exposing an agent as a function tool using `.AsAIFunction()` +- Composing agents where one agent delegates to another +- No server-side agent creation or cleanup required + +## Prerequisites + +- .NET 10 SDK or later +- Azure Foundry service endpoint and deployment configured +- Azure CLI installed and authenticated (`az login`) + +Set the following environment variables: + +```powershell +$env:AZURE_AI_PROJECT_ENDPOINT="https://your-foundry-service.services.ai.azure.com/api/projects/your-foundry-project" +$env:AZURE_AI_MODEL_DEPLOYMENT_NAME="gpt-4o-mini" +``` + +## Run the sample + +```powershell +cd dotnet/samples/02-agents/FoundryAgents-RAPI +dotnet run --project .\FoundryAgentsRAPI_Step11_AsFunctionTool +``` diff --git a/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step12_Middleware/FoundryAgentsRAPI_Step12_Middleware.csproj b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step12_Middleware/FoundryAgentsRAPI_Step12_Middleware.csproj new file mode 100644 index 0000000000..811a1eacb6 --- /dev/null +++ b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step12_Middleware/FoundryAgentsRAPI_Step12_Middleware.csproj @@ -0,0 +1,19 @@ ++ + +Exe +net10.0 + +enable +enable ++ + ++ + + diff --git a/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step12_Middleware/Program.cs b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step12_Middleware/Program.cs new file mode 100644 index 0000000000..c8b4b4f073 --- /dev/null +++ b/dotnet/samples/02-agents/FoundryAgents-RAPI/FoundryAgentsRAPI_Step12_Middleware/Program.cs @@ -0,0 +1,190 @@ +// Copyright (c) Microsoft. All rights reserved. + +// This sample shows multiple middleware layers working together with the Responses API: +// agent run (PII filtering and guardrails), +// function invocation (logging and result overrides), and human-in-the-loop +// approval workflows for sensitive function calls. + +using System.ComponentModel; +using System.Text.RegularExpressions; +using Microsoft.Agents.AI; +using Microsoft.Agents.AI.AzureAI; +using Microsoft.Extensions.AI; + +[Description("Get the weather for a given location.")] +static string GetWeather([Description("The location to get the weather for.")] string location) + => $"The weather in {location} is cloudy with a high of 15°C."; + +[Description("The current datetime offset.")] +static string GetDateTime() + => DateTimeOffset.Now.ToString(); + +AITool dateTimeTool = AIFunctionFactory.Create(GetDateTime, name: nameof(GetDateTime)); +AITool getWeatherTool = AIFunctionFactory.Create(GetWeather, name: nameof(GetWeather)); + +// Create a FoundryAgentClient using environment variable auto-discovery. +// AZURE_AI_PROJECT_ENDPOINT - The Azure AI Foundry project endpoint URL. +// AZURE_AI_MODEL_DEPLOYMENT_NAME - The model deployment name to use. +FoundryAgentClient originalAgent = new( + instructions: "You are an AI assistant that helps people find information.", + name: "InformationAssistant", + tools: [getWeatherTool, dateTimeTool]); + +// Adding middleware to the agent level +AIAgent middlewareEnabledAgent = originalAgent + .AsBuilder() + .Use(FunctionCallMiddleware) + .Use(FunctionCallOverrideWeather) + .Use(PIIMiddleware, null) + .Use(GuardrailMiddleware, null) + .Build(); + +AgentSession session = await middlewareEnabledAgent.CreateSessionAsync(); + +Console.WriteLine("\n\n=== Example 1: Wording Guardrail ==="); +AgentResponse guardRailedResponse = await middlewareEnabledAgent.RunAsync("Tell me something harmful."); +Console.WriteLine($"Guard railed response: {guardRailedResponse}"); + +Console.WriteLine("\n\n=== Example 2: PII detection ==="); +AgentResponse piiResponse = await middlewareEnabledAgent.RunAsync("My name is John Doe, call me at 123-456-7890 or email me at john@something.com"); +Console.WriteLine($"Pii filtered response: {piiResponse}"); + +Console.WriteLine("\n\n=== Example 3: Agent function middleware ==="); +AgentResponse functionCallResponse = await middlewareEnabledAgent.RunAsync("What's the current time and the weather in Seattle?", session); +Console.WriteLine($"Function calling response: {functionCallResponse}"); + +// Special per-request middleware agent. +Console.WriteLine("\n\n=== Example 4: Middleware with human in the loop function approval ==="); + +FoundryAgentClient humanInTheLoopAgent = new( + instructions: "You are a Human in the loop testing AI assistant that helps people find information.", + name: "HumanInTheLoopAgent", + tools: [new ApprovalRequiredAIFunction(AIFunctionFactory.Create(GetWeather, name: nameof(GetWeather)))]); + +AgentResponse response = await humanInTheLoopAgent + .AsBuilder() + .Use(ConsolePromptingApprovalMiddleware, null) + .Build() + .RunAsync("What's the current time and the weather in Seattle?"); + +Console.WriteLine($"HumanInTheLoopAgent agent middleware response: {response}"); + +// Function invocation middleware that logs before and after function calls. +async ValueTask+ + +Exe +net10.0 + +enable +enable ++ + ++ + + ++