From e7f2477e94377b80ca0773042b15afd263c4c510 Mon Sep 17 00:00:00 2001 From: Danyang Chen Date: Fri, 9 Oct 2026 21:03:54 -0700 Subject: [PATCH] Build agent-first website and interactive plugin quickstart --- docs/assets/experience.css | 37 +++++ docs/assets/experience.js | 112 +++++++++++++++ docs/index.md | 277 ++++++------------------------------- docs/install.md | 182 +++--------------------- mkdocs.yml | 5 + 5 files changed, 220 insertions(+), 393 deletions(-) create mode 100644 docs/assets/experience.css create mode 100644 docs/assets/experience.js diff --git a/docs/assets/experience.css b/docs/assets/experience.css new file mode 100644 index 00000000..018b757c --- /dev/null +++ b/docs/assets/experience.css @@ -0,0 +1,37 @@ +:root{--exp-ink:#11152b;--exp-night:#0c1021;--exp-night2:#151a31;--exp-purple:#8069f4;--exp-mint:#6ce3c5;--exp-muted:#737b91;--exp-line:#e5e8f0} +body:has(.experience) .md-header,body:has(.experience) .md-tabs,body:has(.experience) .md-sidebar,body:has(.experience) .md-footer{display:none} +body:has(.experience) .md-main__inner{max-width:none;margin:0;padding:0} +body:has(.experience) .md-content{margin:0!important;max-width:none!important} +body:has(.experience) .md-content__inner{margin:0;padding:0} +body:has(.experience) .md-content__inner:before{display:none} +body:has(.experience) .md-main{min-height:100vh} +.md-typeset .experience{font-size:16px;line-height:1.55;color:var(--exp-ink)} +.experience,.experience *{box-sizing:border-box} +.experience{overflow:hidden} +.experience h1,.experience h2,.experience h3,.experience p{margin-top:0} +.experience h1,.experience h2,.experience h3{font-weight:700;letter-spacing:-.055em;line-height:1.07} +.experience h1{display:block;font-size:clamp(55px,6vw,88px)} +.experience a{text-decoration:none;color:inherit} +.experience button,.experience input,.experience select{font:inherit} +.experience button{cursor:pointer} +.experience em{font-style:normal;background:linear-gradient(100deg,#aa98ff 5%,#69e5cc 96%);background-clip:text;-webkit-background-clip:text;color:transparent} +.exp-nav{height:72px;padding:0 max(calc((100vw - 1230px)/2),6vw);background:#0c1021;color:white;display:flex;align-items:center;justify-content:space-between;border-bottom:1px solid #ffffff16;position:relative;z-index:10} +.exp-brand{display:flex;align-items:center;gap:10px;font-size:15px;font-weight:750;letter-spacing:-.04em;color:white!important} +.brand-mark{height:29px;width:29px;border-radius:8px;display:grid;place-items:center;background:linear-gradient(135deg,#9882ff,#62e5c6);color:#11142c;font-weight:900;font-size:15px;position:relative} +.brand-mark span{position:absolute;right:3px;bottom:0;font-size:12px} +.exp-nav-links{display:flex;align-items:center;gap:30px;font-size:12px;font-weight:600;color:#acb1c7}.exp-nav-links a:hover{color:white}.exp-nav-links .nav-start{border:1px solid #ffffff40;border-radius:6px;padding:10px 14px;color:#fff} +.exp-hero{background:radial-gradient(ellipse at 78% 50%,#37336b60,transparent 52%),#0c1021;color:white;min-height:630px;padding:86px max(calc((100vw - 1230px)/2),6vw) 90px;display:grid;grid-template-columns:.88fr 1.12fr;align-items:center;gap:5%;position:relative} +.hero-noise{pointer-events:none;position:absolute;inset:0;background-image:linear-gradient(#ffffff06 1px,transparent 1px),linear-gradient(90deg,#ffffff06 1px,transparent 1px);background-size:34px 34px;mask-image:linear-gradient(90deg,transparent 20%,black)} +.hero-content{position:relative;z-index:2}.eyebrow,.section-label,.panel-overline,.lab-tag,.product-head,.product-title>span,.product-merge small,.product-bottom,.metric-ribbon>a,.artifact-kicker,.artifact-code>div,.feature-grid small,.qs-breadcrumb,.qs-hero-meta,.ask-card>span{font:700 10px/1.4 "SFMono-Regular",Consolas,monospace;letter-spacing:.12em}.eyebrow{color:#b5afde;display:flex;align-items:center;gap:10px}.pulse-dot{width:7px;height:7px;background:var(--exp-mint);border-radius:50%;display:inline-block;box-shadow:0 0 0 4px #6ce3c51d,0 0 14px var(--exp-mint)} +.exp-hero h1{margin:23px 0 23px;line-height:1.01;color:#fff}.exp-hero p{font-size:16px;color:#aeb5cb;max-width:510px;line-height:1.72;margin-bottom:27px}.hero-ctas{display:flex;gap:11px;flex-wrap:wrap}.exp-button{display:inline-flex!important;align-items:center;justify-content:center;gap:25px;border-radius:7px;font-size:12px;font-weight:750;padding:13px 17px;transition:transform .2s,box-shadow .2s;border:1px solid transparent;text-decoration:none}.exp-button:hover{transform:translateY(-2px)}.exp-button.primary{background:#806af2;color:#fff!important;box-shadow:0 12px 24px #4d3ad252}.exp-button.ghost{background:transparent;color:#dedff0!important;border-color:#ffffff3e}.exp-button.light{background:white;color:#332568!important}.hero-command{display:inline-flex;align-items:center;gap:11px;margin-top:26px;border:1px solid #ffffff20;background:#ffffff0a;padding:8px 10px;border-radius:6px;font:12px Consolas,monospace;color:#d8dbea}.hero-command>span{color:var(--exp-mint)}.exp-copy{border:1px solid #ffffff2c;border-radius:5px;padding:5px 8px;font:10px Consolas,monospace;color:#d9dcf0;background:#ffffff12;white-space:nowrap}.exp-copy:hover{border-color:#a897ff} +.hero-product{position:relative;z-index:1;background:#171c34;border:1px solid #4c4c75;border-radius:11px;box-shadow:0 40px 90px #0009,0 0 0 7px #ffffff05;transform:rotate(1.4deg)}.product-head,.lab-display-top,.art-top{height:43px;display:flex;align-items:center;justify-content:space-between;padding:0 16px;background:#202641;color:#aab1c9;border-radius:10px 10px 0 0;font-size:9px}.product-head>span,.window-dots,.art-top>span{display:flex;gap:5px}.product-head i,.window-dots i,.art-top i{display:block;width:6px;height:6px;border-radius:50%;background:#727891}.product-head small{color:var(--exp-mint);font-size:9px}.product-inner{padding:23px 25px 20px}.product-title{display:flex;flex-direction:column;gap:8px;margin-bottom:17px}.product-title>span{color:#9189da}.product-title b{font-size:20px;letter-spacing:-.04em}.product-tracks{display:grid;gap:7px}.product-tracks>div{border:1px solid #343b5b;background:#202741;display:flex;align-items:center;gap:11px;border-radius:6px;padding:10px 12px}.track-avatar{background:#7968e344;border:1px solid #8c7bef;border-radius:5px;color:#b7a8ff;padding:6px;font:10px monospace}.product-tracks b{font-size:11px;color:#e5e8f3}.product-tracks small{margin-left:auto;color:#969db6;font:10px monospace}.product-tracks i{font-style:normal;color:var(--exp-mint)}.product-connector{display:flex;align-items:center;justify-content:center;gap:10px;height:46px;color:#a996ff}.product-connector span{width:36px;height:1px;background:#7467b7}.product-merge{display:flex;gap:12px;align-items:center;padding:12px;background:#303052;border:1px solid #6b61ad;border-radius:6px}.merge-emblem{width:36px;height:36px;display:grid;place-items:center;border-radius:6px;background:#806af2;color:white;font-size:19px}.product-merge>div{display:flex;flex-direction:column;gap:4px}.product-merge small{color:#b6aaff;font-size:8px}.product-merge strong{font-size:12px}.merge-arrow{margin-left:auto;color:var(--exp-mint)}.product-bottom{display:flex;align-items:center;gap:11px;margin-top:16px;padding-top:14px;border-top:1px solid #ffffff20;color:#b8bfd2;font-size:9px}.product-bottom>span{color:var(--exp-mint);border:1px solid #53cdab77;padding:4px;border-radius:3px}.product-bottom small{margin-left:auto;color:#70e1c4;font-size:9px}.product-glow{position:absolute;inset:-35px;z-index:-1;background:#7868f346;filter:blur(70px)}.hero-scroll{position:absolute;left:50%;bottom:23px;transform:translateX(-50%);color:#8c93ad!important;font:9px monospace;letter-spacing:.14em}.hero-scroll span{color:var(--exp-mint);margin-left:8px} +.metric-ribbon{background:#f6f7fb;padding:27px max(calc((100vw - 1230px)/2),6vw);display:grid;grid-template-columns:repeat(3,1fr) 1.25fr;gap:20px;border-bottom:1px solid var(--exp-line);align-items:center}.metric-ribbon>div{display:flex;gap:13px;align-items:center}.metric-ribbon strong{font-size:27px;letter-spacing:-.06em}.metric-ribbon span{font-size:10px;color:#737c91;line-height:1.4}.metric-ribbon>a{justify-self:end;color:#6051c6!important;font-size:9px}.metric-ribbon>a span{color:inherit} +.exp-section{padding:100px max(calc((100vw - 1100px)/2),8vw)}.section-label{color:#6f5fd5;margin-bottom:25px}.idea{background:#fff}.idea-grid{display:grid;grid-template-columns:1.1fr .9fr;gap:80px}.idea-grid h2,.inside-heading h2,.architecture-teaser h2,.qs-simple h2,.qs-flow h2,.qs-next-section h2{font-size:clamp(36px,4.5vw,56px)}.idea-grid h2 span{color:#828a9e}.idea-grid p{color:#6f798e;font-size:15px;line-height:1.8}.inline-link{display:inline-flex;gap:16px;color:#6250cd!important;font-size:12px;font-weight:750;margin-top:12px}.idea-rail{display:flex;justify-content:space-between;align-items:center;gap:9px;margin-top:65px;border-top:1px solid #dee2ec;padding-top:22px}.idea-rail>div{display:flex;flex-direction:column;gap:6px}.idea-rail>div>span{color:#8977e4;font:10px monospace}.idea-rail b{font-size:15px}.idea-rail small{color:#8a92a6;font-size:10px}.idea-rail>i{font-style:normal;color:#b1b7c7} +.exp-lab{background:#10152a;color:white;padding:100px max(calc((100vw - 1100px)/2),8vw)}.exp-lab .section-label{color:#a28dff}.lab-heading{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:33px;gap:25px}.lab-heading h2{font-size:clamp(38px,4.7vw,57px);margin-bottom:12px}.lab-heading p{color:#a9b0c4;font-size:14px;margin:0}.lab-tag{display:flex;align-items:center;gap:9px;padding:10px 12px;border:1px solid #ffffff30;border-radius:30px;color:#aeb6ce;font-size:9px;white-space:nowrap}.lab-tag .pulse-dot{width:5px;height:5px}.agent-demo{display:grid;grid-template-columns:290px 1fr;background:#1a2036;border:1px solid #3b4260;border-radius:11px;overflow:hidden;box-shadow:0 28px 65px #0005}.demo-config{padding:25px;border-right:1px solid #343b53}.panel-overline{color:#9187c6;font-size:9px}.control-title{font-size:11px;color:#d1d6e6;margin:26px 0 11px;font-weight:650}.demo-hosts{display:grid;grid-template-columns:1fr 1fr;gap:7px}.demo-hosts button,.demo-presets button{border:1px solid #444c69;background:#242c47;border-radius:5px;color:#b8bfd3;padding:9px 7px;font-size:10px;text-align:left}.demo-hosts button.active,.demo-presets button.active{background:#715fe24a;border-color:#9787ff;color:white}.demo-target-title{margin-top:22px}.demo-presets{display:flex;gap:5px;flex-wrap:wrap}.demo-presets button{font-size:9px;padding:7px}.demo-path-label{display:block;color:#9ca6be;margin-top:19px;font-size:10px}.demo-config input{width:100%;margin-top:6px;border:1px solid #444c69;background:#11182c;border-radius:5px;color:#f4f3ff;padding:10px;font:11px Consolas,monospace}.control-help{color:#8a94ad;font-size:10px;margin:7px 0 0}.lab-run{margin-top:25px;width:100%}.lab-run:disabled{opacity:.7;cursor:wait}.lab-config-note{display:flex;gap:10px;color:#838ea8;margin-top:18px;align-items:start}.lab-config-note>span{font-size:19px;color:#8c83d3}.lab-config-note p{font-size:10px;margin:0;line-height:1.5}.demo-chat{display:flex;flex-direction:column;min-width:0;min-height:460px}.lab-display-top{border-radius:0;background:#242c47;flex-shrink:0}.lab-display-top>div{display:flex;align-items:center;gap:12px}.lab-display-top b{font-size:9px;letter-spacing:.1em}.lab-display-top>span{font:9px monospace;color:var(--exp-mint)}.demo-chat-body{flex:1;padding:22px;overflow:auto;max-height:520px}.demo-welcome{height:100%;min-height:320px;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;color:#8d98b2}.demo-welcome>span{font-size:38px;color:#a997ff;margin-bottom:10px}.demo-welcome strong{font-size:17px;color:#e7e9f1}.demo-welcome small{font-size:11px;margin-top:8px}.demo-message{display:flex;gap:11px;margin-bottom:13px;animation:exp-in .3s ease both}.demo-message .message-icon{width:26px;height:26px;flex:0 0 26px;border-radius:6px;display:grid;place-items:center;background:#6959c7;color:white;font-size:13px}.demo-message.user .message-icon{background:#38415e}.message-content{background:#242c47;border:1px solid #3d4562;border-radius:7px;padding:10px 13px;flex:1;min-width:0}.demo-message.user .message-content{background:#293149}.message-content small{color:#a895ff;font:9px monospace;letter-spacing:.08em}.message-content p{font-size:11px;color:#e3e6f3;line-height:1.55;margin:5px 0 0;overflow-wrap:anywhere}.message-content code{color:#79e5ca}.message-content .message-detail{color:#aab4ca}.demo-chat-footer{border-top:1px solid #333b54;padding:12px 17px;display:flex;align-items:center;justify-content:space-between;gap:10px;background:#202840}.demo-chat-footer>div{display:flex;align-items:center;gap:7px;color:#8f9ab5;font:9px Consolas,monospace}.tool-light{width:6px;height:6px;border-radius:50%;background:#70dfbe}.demo-chat-footer button{background:#69d8ba;border:0;color:#0f2430;border-radius:5px;padding:7px 9px;font-size:9px;font-weight:700;white-space:nowrap}.demo-chat-footer button[hidden]{display:none}.lab-under{display:flex;justify-content:space-between;color:#8f9bb5;font-size:11px;padding-top:19px}.lab-under a{color:#9c8bff!important;font-weight:700} +.inside{background:#f7f8fc}.inside-heading{display:flex;justify-content:space-between;align-items:end;gap:50px}.inside-heading p{max-width:320px;color:#80899d;font-size:14px;line-height:1.75}.artifact-picker{display:flex;border-bottom:1px solid #d9deea;gap:25px;margin-top:28px}.artifact-picker button{border:0;border-bottom:2px solid transparent;background:none;padding:14px 3px;color:#8a91a1;font-size:12px;font-weight:700}.artifact-picker button.active{color:#6653d5;border-color:#7662ec}.artifact-view{display:grid;grid-template-columns:1fr 1fr;gap:55px;align-items:center;padding-top:33px}.artifact-kicker{color:#806ee0;font-size:9px}.artifact-view h3{font-size:29px;margin:15px 0}.artifact-view p{color:#7a8497;font-size:13px;max-width:350px;line-height:1.75}.artifact-code{background:#192039;border-radius:8px;color:#e7eaf5;overflow:hidden;box-shadow:0 18px 40px #131c3825}.artifact-code>div{padding:12px 16px;background:#252c48;color:#aaa9d8;display:flex;justify-content:space-between;font-size:9px}.artifact-code>div small{color:#90d6c4}.artifact-code pre{background:transparent!important;color:#dce4f6;font:11px/1.8 Consolas,monospace;white-space:pre-wrap;padding:19px!important;min-height:150px;margin:0!important}.architecture-teaser{background:white}.architecture-teaser h2{margin-bottom:37px}.feature-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.feature-grid a{display:block;border:1px solid #e3e6ef;border-radius:8px;padding:22px;transition:transform .2s,box-shadow .2s}.feature-grid a:hover{transform:translateY(-3px);box-shadow:0 15px 35px #10152a12}.feature-grid a>span{font-size:22px;color:#7463df}.feature-grid h3{font-size:18px;margin:27px 0 10px}.feature-grid p{font-size:12px;color:#818a9d;line-height:1.7;min-height:60px}.feature-grid small{color:#725ed1;font-size:9px}.exp-cta{background:linear-gradient(105deg,#684fd2,#786de8 56%,#4bbfae);color:white;padding:54px max(calc((100vw - 1100px)/2),8vw);display:flex;align-items:center;justify-content:space-between;gap:30px}.exp-cta .section-label{color:#d6d2ff;font-size:9px}.exp-cta h2{font-size:39px;margin:0 0 9px}.exp-cta p{margin:0;color:#f1efff;font-size:12px}.exp-footer{background:#0c1021;color:#9ba4be;padding:22px max(calc((100vw - 1100px)/2),8vw);display:flex;align-items:center;justify-content:space-between;font-size:11px}.exp-footer>span{color:#fff;font-weight:700}.exp-footer small{color:#848da5;font-weight:400;margin-left:10px}.exp-footer>div{display:flex;gap:22px} +/* Quickstart */ +.exp-quickstart{background:#fff}.light-nav{background:#fff;color:#19213a;border-bottom:1px solid #e6e9f1}.light-nav .exp-brand{color:#151a2f!important}.light-nav .exp-nav-links{color:#6d768b}.light-nav .exp-nav-links a:hover{color:#5541bd}.light-nav .exp-nav-links .nav-start{color:#6150c9;border-color:#d9d2ff}.qs-hero{position:relative;background:#f6f7fc;padding:31px max(calc((100vw - 1100px)/2),8vw) 88px;overflow:hidden}.qs-hero-glow{position:absolute;right:2%;top:11%;height:480px;width:540px;background:radial-gradient(ellipse,#cfc7ff9e,transparent 70%);pointer-events:none}.qs-breadcrumb{display:flex;gap:12px;color:#9da5b8;font-size:9px}.qs-breadcrumb a{color:#7c6bdd!important}.qs-hero-grid{display:grid;grid-template-columns:1fr 1fr;gap:65px;align-items:center;margin-top:48px;position:relative}.qs-hero .eyebrow{color:#7262d7}.qs-hero h1{font-size:clamp(50px,5.7vw,75px);margin:18px 0 21px}.qs-hero h1 em{background-image:linear-gradient(100deg,#7d64e5,#1cb9a5)}.qs-hero p{color:#737d93;font-size:15px;line-height:1.75;max-width:460px;margin-bottom:25px}.qs-hero-meta{display:flex;gap:19px;color:#8c95a9;margin-top:24px;font-size:9px}.qs-hero-art{background:#192038;color:#e7eaf3;border:1px solid #414c69;border-radius:10px;box-shadow:0 35px 60px #151d3640;transform:rotate(1deg);overflow:hidden}.art-top{border-radius:0;height:39px;justify-content:flex-start;gap:12px;font-size:10px;text-transform:none;letter-spacing:0}.art-chat{padding:23px}.chat-user{margin-left:60px;background:#333956;border:1px solid #515779;padding:10px 13px;border-radius:8px}.chat-user small,.chat-tool small{font:9px Consolas,monospace;color:#b3a6ff}.chat-user p,.chat-tool p{font-size:11px;color:#e0e6f2;margin:4px 0 0;line-height:1.5}.chat-tool{display:flex;gap:10px;margin-top:16px}.chat-tool>span{width:26px;height:26px;display:grid;place-items:center;border-radius:6px;background:#745de3}.chat-tool>div{flex:1;border:1px solid #3f4a68;border-radius:7px;padding:9px 11px;background:#252d49}.qs-simple{padding:94px max(calc((100vw - 1100px)/2),8vw)}.qs-simple h2{margin-bottom:40px}.simple-steps{border-top:1px solid #e3e7ee}.simple-steps article{display:grid;grid-template-columns:42px minmax(175px,.68fr) minmax(300px,1.32fr);gap:23px;border-bottom:1px solid #e3e7ee;padding:29px 0;align-items:start}.simple-steps article>span{display:grid;place-items:center;width:30px;height:30px;border-radius:50%;background:#ede9ff;color:#6c57d7;font:10px Consolas,monospace}.simple-steps h3{font-size:20px;margin:0 0 10px}.simple-steps p{font-size:12px;color:#7e889c;line-height:1.7;margin:0}.simple-steps code{color:#6654ce;background:#f1efff;border-radius:3px;padding:1px 3px}.mini-code{background:#172038;border-radius:7px;color:#e3eaf7;display:flex;align-items:flex-start;padding:13px 15px;gap:8px;min-width:0}.mini-code pre{background:none!important;color:#e1e8f4!important;font:10px/1.9 Consolas,monospace!important;white-space:pre-wrap;overflow-wrap:anywhere;flex:1;margin:0!important;padding:0!important}.mini-code .exp-copy{flex-shrink:0;font-size:9px}.host-config{min-width:0}.host-tabs{display:flex;flex-wrap:wrap;gap:4px;margin-bottom:9px}.host-tabs button{background:#f1f2f8;border:1px solid #e3e5ef;border-radius:5px;color:#70798f;padding:7px 9px;font-size:10px;font-weight:650}.host-tabs button.active{background:#e9e4ff;border-color:#bbb0f9;color:#5e4dc0}.host-help{margin-top:8px!important;font-size:10px!important}.ask-card{background:#f5f3ff;border:1px solid #dad5fb;border-radius:8px;padding:17px;position:relative}.ask-card>span{color:#7463d6;font-size:9px}.ask-card p{font-size:13px!important;color:#29304b!important;margin:10px 0 12px!important}.ask-card .exp-copy{background:#745fe7;color:white;border:0}.qs-flow{background:#10162b;color:#fff;padding:78px max(calc((100vw - 1100px)/2),8vw);display:grid;grid-template-columns:.85fr 1.15fr;gap:80px}.qs-flow .section-label{color:#a798ff}.qs-flow h2{margin-bottom:16px}.qs-flow p{color:#a8b1c7;font-size:13px;line-height:1.75}.flow-list>div{display:grid;grid-template-columns:45px 1fr;gap:5px 15px;padding:14px 0;border-bottom:1px solid #3c4560}.flow-list>div:first-child{padding-top:0}.flow-list span{grid-row:span 2;color:#a999ff;font:12px Consolas,monospace}.flow-list b{font-size:15px}.flow-list small{color:#8997b4;font-size:11px}.qs-secondary{background:#f7f8fc;padding:90px max(calc((100vw - 1100px)/2),8vw)}.secondary-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px}.secondary-grid article{border:1px solid #e3e6f0;background:#fff;border-radius:9px;padding:21px}.secondary-grid article>span{font-size:22px;color:#826ee4}.secondary-grid h3{font-size:17px;margin:18px 0 10px}.secondary-grid p{font-size:11px;color:#7b859a;line-height:1.7;min-height:74px}.secondary-grid a{font-size:11px;color:#6651ca!important;font-weight:750}.secondary-command{display:flex;align-items:center;justify-content:space-between;gap:6px;padding:8px 9px;background:#f0edff;border-radius:5px}.secondary-command code{font-size:10px;color:#5041a5}.secondary-command .exp-copy{color:#6551c5;border-color:#d2cafa;background:#fff}.qs-final{padding-top:42px;padding-bottom:42px} +@keyframes exp-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:translateY(0)}} +@media(max-width:900px){.exp-nav,.exp-hero,.metric-ribbon,.exp-section,.exp-lab,.exp-cta,.exp-footer,.qs-hero,.qs-simple,.qs-flow,.qs-secondary{padding-left:6vw;padding-right:6vw}.exp-hero{grid-template-columns:1fr;gap:55px}.hero-product{max-width:680px;width:100%;margin:auto}.metric-ribbon{grid-template-columns:repeat(3,1fr)}.metric-ribbon>a{grid-column:1/-1;justify-self:start}.idea-grid,.qs-hero-grid{gap:35px}.agent-demo{grid-template-columns:250px 1fr}.simple-steps article{grid-template-columns:38px 1fr;gap:14px}.simple-steps article>:last-child{grid-column:2}.qs-flow{gap:40px}} +@media(max-width:620px){.exp-nav{height:60px}.exp-nav-links{gap:11px}.exp-nav-links a:not(.nav-start){display:none}.exp-brand{font-size:13px}.exp-hero{padding-top:65px;padding-bottom:75px}.exp-hero h1{font-size:56px}.exp-hero p{font-size:14px}.hero-product{transform:none}.product-inner{padding:17px}.product-tracks small{display:none}.hero-scroll{display:none}.metric-ribbon{grid-template-columns:1fr 1fr}.metric-ribbon>a{grid-column:1/-1}.exp-section,.exp-lab{padding-top:72px;padding-bottom:72px}.idea-grid,.inside-heading,.artifact-view,.qs-hero-grid,.qs-flow{display:block}.idea-grid h2,.inside-heading h2,.architecture-teaser h2,.qs-simple h2,.qs-flow h2{font-size:38px}.idea-grid>div{margin-top:24px}.idea-rail{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:40px}.idea-rail>i{display:none}.lab-heading{display:block}.lab-heading h2{font-size:39px}.lab-tag{display:inline-flex;margin-top:20px}.agent-demo{grid-template-columns:1fr}.demo-config{border-right:0;border-bottom:1px solid #38415c;padding:20px}.demo-chat{min-height:380px}.demo-chat-body{padding:15px}.demo-chat-footer{align-items:start;flex-direction:column}.demo-chat-footer button{align-self:flex-end}.lab-under{gap:15px}.artifact-picker{gap:10px}.artifact-picker button{font-size:10px}.artifact-view>div:first-child{margin-bottom:25px}.feature-grid,.secondary-grid{grid-template-columns:1fr}.feature-grid p{min-height:0}.exp-cta{align-items:start;flex-direction:column}.exp-cta h2{font-size:32px}.exp-footer{gap:14px;flex-wrap:wrap}.exp-footer small{display:block;margin:4px 0 0}.qs-hero{padding-bottom:60px}.qs-hero-grid{margin-top:40px}.qs-hero h1{font-size:52px}.qs-hero-art{margin-top:45px;transform:none}.qs-hero-meta{flex-wrap:wrap;gap:8px 14px}.qs-simple{padding-top:70px;padding-bottom:70px}.simple-steps article{grid-template-columns:28px 1fr;gap:10px}.simple-steps article>:last-child{grid-column:1/-1}.host-tabs button{font-size:9px}.qs-flow>div:last-child{margin-top:30px}.secondary-grid{gap:9px}.secondary-grid p{min-height:0}} +.qs-technical{padding:26px max(calc((100vw - 1100px)/2),8vw) 48px;background:#f7f8fc}.qs-technical details{border-top:1px solid #e1e5ed;padding:14px 0}.qs-technical details:last-child{border-bottom:1px solid #e1e5ed}.qs-technical summary{cursor:pointer;color:#4f5873;font-size:11px;font-weight:700}.qs-technical p{color:#7e8798;font-size:11px;line-height:1.7;max-width:780px;margin:12px 0 0} diff --git a/docs/assets/experience.js b/docs/assets/experience.js new file mode 100644 index 00000000..e213934d --- /dev/null +++ b/docs/assets/experience.js @@ -0,0 +1,112 @@ +(() => { + const $ = (selector) => document.querySelector(selector); + const $$ = (selector) => [...document.querySelectorAll(selector)]; + const copy = async (text, button) => { + try { + await navigator.clipboard.writeText(text); + const before = button.textContent; + button.textContent = 'Copied ✓'; + setTimeout(() => { button.textContent = before; }, 1300); + } catch (_) { + button.title = 'Clipboard unavailable; select the adjacent text to copy.'; + } + }; + $$('[data-copy]').forEach((button) => button.addEventListener('click', () => copy(button.dataset.copy, button))); + + const hosts = { + claude: {name: 'CLAUDE CODE', label: 'Claude Code', setup: 'agentdescent install claude-code\nclaude --plugin-dir ~/.agentdescent/plugins/claude-code', help: 'Start Claude Code with the plugin directory. In the session, /plugin lists it.'}, + codex: {name: 'CODEX', label: 'Codex', setup: 'codex plugin marketplace add Birfy/agentdescent\ncodex plugin add agentdescent@agentdescent\ncodex mcp list', help: 'The marketplace plugin includes the AgentDescent MCP server. Confirm that codex mcp list shows it.'}, + opencode: {name: 'OPENCODE', label: 'OpenCode', setup: 'agentdescent install opencode\nopencode mcp list', help: 'Restart OpenCode after installation and check that AgentDescent is connected.'}, + dsh: {name: 'DEEPSEEK HARNESS', label: 'DeepSeek Harness', setup: 'agentdescent install dsh\ndsh --profile web --dump-config | grep agentdescent', help: 'Restart DeepSeek Harness and check that its configuration contains AgentDescent.'} + }; + $$('.host-tabs button').forEach((button) => button.addEventListener('click', () => { + $$('.host-tabs button').forEach((item) => { item.classList.toggle('active', item === button); item.setAttribute('aria-selected', String(item === button)); }); + const host = hosts[button.dataset.host]; + $('#qs-host-command').textContent = host.setup; + $('#qs-host-help').textContent = host.help; + })); + $('#qs-host-copy')?.addEventListener('click', (event) => copy($('#qs-host-command').textContent, event.currentTarget)); + + const artifacts = { + prompt: {kicker: 'SINGLE SLOT STRATEGY', title: 'Evolve one instruction.', copy: 'Start from a prompt and search for a stronger version against your tasks.', filename: 'prompt.md', preview: 'You are a helpful assistant.\n\n+ Respond with only the requested answer.\n+ Omit extra explanation and restatement.', link: 'quickstart-skill/', linkText: 'Read the prompt quickstart'}, + skill: {kicker: 'FILE TREE STRATEGY', title: 'Improve a skill folder.', copy: 'Let workers edit the files your coding agent reads, then review the resulting diff.', filename: 'skills/pdf-audit/SKILL.md', preview: '# PDF audit\n\n+ Verify every section before reporting.\n+ Cite the page for each finding.\n\nreferences/rules.md · unchanged', link: 'quickstart-directory/', linkText: 'Read the directory quickstart'}, + code: {kicker: 'AGENT CODE STRATEGY', title: 'Evolve an agent’s code.', copy: 'Search across files while keeping tests and evaluation boundaries fixed.', filename: 'agent/solver.py', preview: 'def solve(task):\n context = retrieve(task)\n+ context = rank_evidence(context)\n return answer(context, task)', link: 'quickstart-agent-code/', linkText: 'Read the code quickstart'} + }; + $$('.artifact-picker button').forEach((button) => button.addEventListener('click', () => { + $$('.artifact-picker button').forEach((item) => { item.classList.toggle('active', item === button); item.setAttribute('aria-selected', String(item === button)); }); + const artifact = artifacts[button.dataset.artifact]; + $('#artifact-kicker').textContent = artifact.kicker; + $('#artifact-title').textContent = artifact.title; + $('#artifact-copy').textContent = artifact.copy; + $('#artifact-filename').textContent = artifact.filename; + $('#artifact-preview').textContent = artifact.preview; + $('#artifact-link').href = artifact.link; + $('#artifact-link').innerHTML = `${artifact.linkText} ↗`; + })); + + const demoBody = $('#demo-chat-body'); + if (!demoBody) return; + const kinds = { + skill: {path:'~/.claude/skills/pdf-audit', noun:'skill', example:'Add a check for missing appendix pages'}, + prompt: {path:'./prompts/answer.md', noun:'prompt', example:'Answer concisely and cite the source'}, + code: {path:'./agent/solver.py', noun:'agent code', example:'Rank retrieved evidence before answering'} + }; + let activeHost = 'claude'; + let activeKind = 'skill'; + let phase = 0; + const approve = $('#demo-approve'); + const start = $('#demo-run'); + const status = $('#demo-status'); + const toolLine = $('#demo-tool-line'); + const pause = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); + function addMessage(kind, label, text, detail) { + const article = document.createElement('div'); + article.className = `demo-message ${kind}`; + const icon = document.createElement('span'); icon.className = 'message-icon'; icon.textContent = kind === 'user' ? '●' : '✳'; + const body = document.createElement('div'); body.className = 'message-content'; + const small = document.createElement('small'); small.textContent = label; + const paragraph = document.createElement('p'); paragraph.textContent = text; + body.append(small, paragraph); + if (detail) { const extra = document.createElement('p'); extra.className = 'message-detail'; extra.textContent = detail; body.append(extra); } + article.append(icon, body); demoBody.append(article); demoBody.scrollTop = demoBody.scrollHeight; + } + function setActive(selector, selected) { $$(selector).forEach((button) => { const active = button === selected; button.classList.toggle('active', active); if (button.getAttribute('role') === 'tab') button.setAttribute('aria-selected', String(active)); }); } + $$('.demo-hosts button').forEach((button) => button.addEventListener('click', () => { + activeHost = button.dataset.demoHost; setActive('.demo-hosts button', button); + $('#demo-window-title').textContent = `${hosts[activeHost].name} / AGENTDESCENT`; + })); + $$('.demo-presets button').forEach((button) => button.addEventListener('click', () => { + activeKind = button.dataset.demoKind; setActive('.demo-presets button', button); + $('#demo-path').value = kinds[activeKind].path; + })); + start.addEventListener('click', async () => { + if (start.disabled) return; + start.disabled = true; phase = 0; approve.hidden = true; demoBody.replaceChildren(); + const path = $('#demo-path').value.trim() || kinds[activeKind].path; + const kind = kinds[activeKind]; + status.textContent = 'PLANNING'; toolLine.textContent = 'Calling doctor and plan…'; + addMessage('user', 'YOU', `Improve the ${kind.noun} at ${path}. Show the plan and call count before starting.`); + await pause(460); + addMessage('tool', 'AGENTDESCENT · DOCTOR', 'Checked the agent, provider configuration and run store.', 'No files changed.'); + await pause(580); + addMessage('tool', 'AGENTDESCENT · PLAN', 'Sample plan: 12 cases · 4 workers · up to 48 agent calls.', 'Please review the plan and cost before starting.'); + status.textContent = 'AWAITING APPROVAL'; toolLine.textContent = 'Plan ready · no run started'; + approve.textContent = 'Approve sample run ↗'; approve.hidden = false; phase = 1; start.disabled = false; + }); + approve.addEventListener('click', async () => { + approve.hidden = true; + if (phase === 1) { + phase = 0; status.textContent = 'RUNNING'; toolLine.textContent = 'start → status → show'; + addMessage('user', 'YOU', 'The plan looks good. Start the sample run.'); + await pause(380); addMessage('tool', 'AGENTDESCENT · START', 'Started a background evolution run.'); + await pause(550); addMessage('tool', 'AGENTDESCENT · STATUS', 'Workers proposed edits; the aggregator evaluated the candidate.'); + await pause(550); addMessage('tool', 'AGENTDESCENT · SHOW', `Proposed diff: + ${kinds[activeKind].example}.`, 'The real artifact remains untouched until you approve apply.'); + status.textContent = 'DIFF READY'; toolLine.textContent = 'Diff ready · waiting for apply approval'; + approve.textContent = 'Approve sample apply ↗'; approve.hidden = false; phase = 2; + } else if (phase === 2) { + phase = 0; addMessage('user', 'YOU', 'Apply the sample result.'); + await pause(350); addMessage('tool', 'AGENTDESCENT · APPLY', 'Sample change applied; the original is backed up.', 'This page is only a simulation and changed no files.'); + status.textContent = 'COMPLETE'; toolLine.textContent = 'Sample workflow complete · no real files changed'; + } + }); +})(); diff --git a/docs/index.md b/docs/index.md index 8f727cf5..434ec116 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,235 +1,50 @@ --- -description: AgentDescent puts the deep-learning training stack on top of self-evolving LLM agents: diffs are the gradients, and the aggregator is the optimizer step. +description: Explore AgentDescent, the open-source framework for parallel self-evolving agents. Try an interactive merge simulation and start with an offline demo. --- -# AgentDescent - -**Gradient descent — but the parameters are agents.** A parallel, asynchronous -framework for self-evolving agents (skills, prompts, harnesses) where **diffs are -the gradients** and **the aggregator is the optimizer**. - -AgentDescent puts the *deep-learning training stack* on top of agents — data / -tensor / pipeline parallelism, parameter servers, decoupled/asynchronous RL, -partial rollout — applied to recursive self-improvement, where the "parameters" -are a **library of evolvable artifacts** (skills, prompts, harness modules, -verifiers) and the "gradients" are **diffs carrying evidence cards**. - -!!! quote "The core observation" - Serial RSI is bounded at **1 diff / T_iter**. AgentDescent runs *N* workers in - parallel and merges their diffs into a shared, versioned artifact library, - targeting **O(N / T_iter)** improvement throughput. - -The one place the analogy *must* break defines the whole system: - -!!! warning "Gradients add, diffs do not" - Aggregation is therefore **not averaging** but **conflict resolution + - statistical acceptance + transactional commit**. That merge is what - [`aggregator.py`](aggregator.md) implements. - ---- - -## Start here - -### Have a dataset - -That is the whole input. - -```python -from agentdescent import SingleSlot, evolve, openai_compatible, reflector, scorer, tasks_from -from agentdescent.dataloader import hf_rows - -rows = hf_rows("hotpotqa/hotpot_qa", "validation", config="distractor", limit=40) -model = openai_compatible(model="deepseek-v4-flash") - -tasks = tasks_from(rows, prompt="question", gold="answer") # rows -> Task objects -run = lambda skill, task: model(f"{skill}\n\n{task.prompt}") # the skill meets the question - -result = evolve(tasks, scorer("exact"), run=run, propose=reflector(model), - strategy=SingleSlot(initial_value="You are a helpful assistant."), - rounds=8, n_workers=8, max_concurrency=8, held_out_frac=0.3, - patience=3, target_reward=0.98) - -print(result.rendered) # the skill it learned -print(result.final_reward) # held-out reward -print(result.outcomes()) # why it went that way -``` - -Run as written, that lifted held-out exact match from **0.167 to 0.583** and wrote -*"Respond with only the requested answer, omitting any extra explanation or -restatement."* — see [Quickstart](quickstart-skill.md) for the full measurement. - -### Have a directory - -A skill folder, a folder of subagent definitions, or the agent's own code: - -```python -from agentdescent import FileTree, evolve, load_tree, scorer, tree_reflector, tree_runner -from agentdescent.agents import claude_code, openai_compatible -from agentdescent.governance import SKILL_BLAST_RADIUS - -path = "~/.claude/skills/pdf-audit" # your directory -tree = load_tree(path) # -> {"SKILL.md": ..., ...} -strategy = FileTree(tree, max_files_per_diff=2) # file paths are the state keys -run = tree_runner(claude_code(extra_args=["--permission-mode", "acceptEdits"]), - layout="claude_skill", name="pdf-audit", - overlay=strategy.frozen_files(tree)) # a fresh workspace per rollout - -result = evolve(tasks, scorer("contains"), run=run, strategy=strategy, - propose=tree_reflector(openai_compatible(model="deepseek-v4-flash"), - strategy=strategy), - artifact_id="pdf-audit", blast_radius=SKILL_BLAST_RADIUS, # L2 - self_verify=False, cheap_eval_tasks=4, # a rollout is a real agent call - rounds=6, n_workers=4, max_concurrency=4, held_out_frac=0.3) - -result.write_to(path) # opt in; backs up first -``` - -Each rollout materialises the candidate into a throwaway workspace and a **real -agent reads the files off disk**. See -[Quickstart — a directory](quickstart-directory.md). - -Neither is a separate system: both build ordinary arguments and call -[`evolve()`](evolution.md), which is where you go the moment you want more. - -```bash -pip install agentdescent -``` - ---- - -## Where to go next - -
- -- :material-download: **[Install and first run](install.md)** — start here - - Install, then reproduce the central claim in seconds with no API key. - -- :material-rocket-launch: **[Quickstart — dataset to skill](quickstart-skill.md)** - - One call, three decisions: your data, how to score it, which model. With the - measured result of running it. - -- :material-folder-cog: **[Quickstart — a directory](quickstart-directory.md)** - - A skill folder, an agent folder, or its code — evolved by an agent that reads - the files. - -- :material-power-plug: **[Use it from your agent](plugins.md)** - - The plugin for DeepSeek Harness, Claude Code and Codex: say "evolve this" - inside the agent. Also evolves the plugins themselves. New here? Start with - [the plugin in three commands](plugin-quickstart.md) — `agentdescent demo` - from current `main` runs a whole evolution with no API key. - -- :material-star-four-points: **[The `evolve` method](evolution.md)** - - The one entry point underneath. Every capability is a plug-in to one - `evolve()` parameter — this is the map, with an example per module. - -- :material-lightbulb-on: **[Concepts](concepts.md)** - - The *why*: the training↔RSI analogy, staleness, the aggregator as a - discrete-space optimizer, the three long tails, governance. - -- :material-sitemap: **[Architecture](architecture.md)** - - How the components fit together and how a diff travels from a worker to a - committed change. - -- :material-view-grid-plus: **[Module map](modules.md)** - - Every module, what it is for, and a reading order for whatever you are doing. - -- :material-api: **[API reference](api.md)** - - Every public name with its real signature — generated from the code, and - tested against it. - -- :material-chart-box: **[Measured results](results.md)** - - Every empirical claim with the setup that produced it — including the - benchmarks where the honest answer is "nothing to learn here". - +
+ + +
+ +
+
OPEN SOURCE FRAMEWORK · PYTHON 3.9+
+

Agents get better.
Together.

+

Give Claude Code, Codex or another agent a task: improve this skill. AgentDescent plans the run, explores changes in parallel and returns a diff for you to review.

+ +
$pip install agentdescent
+
+
+
AGENTDESCENT / EVOLUTION RUN● LIVE LOOP
+
01 / PARALLEL EXPLORATIONThree workers. Three ideas.
+
01Improve answer format+ rules.md✓
02Add citation behavior+ citations.md✓
03Refine reasoning~ prompt.md✓
+
⤨
✳
CONFLICT-AWARE AGGREGATORMerge → verify → commit
↗
+
v.08Shared library updated3 compatible edits accepted
+
+ +
+ SCROLL TO EXPLORE ↓ +
+ +
20published methods
with runnable ports
6.8×median speedup in the
reported GEPA setting*
40%fewer model calls in the
reported merge setting*
* See measured settings & limitations ↗
+ +

Diffs are the gradients.
But diffs don’t add.

AgentDescent treats prompts, skills and code as evolving artifacts. Workers explore a shared snapshot and propose edits with evidence. The aggregator decides which edits can coexist, verifies the result and writes an accepted version to the ledger.

Follow a diff through the system ↗
01ExploreN workers try tasks in parallel
→
02ProposeDiffs carry evidence
→
03ResolveFuse or handle conflicts
→
04CommitVersioned, inspectable result
+ +

Stay in your agent.
Improve what it uses.

See the plugin workflow as it appears inside Claude Code, Codex, OpenCode or DeepSeek Harness.

TRY A SAMPLE CONVERSATION
+
PICK YOUR WORKSPACE
01   Your agent
02   What to improve

Change the path to personalize the sample conversation.

◇

Illustrative browser demo. No agent runs, model calls or file changes.

+
CLAUDE CODE / AGENTDESCENT
READY
✳Your agent can run the whole loop.Choose a host, then start the sample conversation.
The agent shows the plan and diff before changing your files.Set up your agent ↗
+
+ +

What should your
agent learn?

One engine, multiple representations. The key space determines which concurrent edits can merge.

SINGLE SLOT STRATEGY

Evolve one instruction.

Start from a prompt and let the loop search for a stronger version against your tasks.

Read the prompt quickstart ↗
ARTIFACT PREVIEWprompt.md
You are a helpful assistant.
+
++ Respond with only the requested answer.
++ Omit extra explanation and restatement.
+ +

One loop.
Many ways to make it yours.

+ +

See the loop for yourself.

No API key needed for the current main branch’s offline demo.

Open Quickstart ↗
+
- -**Building blocks** (each plugs into `evolve`): -- **[The decision plane](policies.md)** — every replaceable decision (selection, sampling, merge, acceptance, promotion) in one `Policies` bundle - -
- -- :material-connection: **[Agents & LLMs](agents.md)** → `agent=` - - Any `prompt -> text` is a completion: Claude, GLM/OpenAI-compatible, a CLI - coding agent, a callable, a stub. - -- :material-file-tree: **[Strategies](strategies.md)** → `strategy=` - - What the artifact *is*: one slot, a playbook, keyed categories, or a - directory. The key space is the design decision. - -- :material-cog-sync: **[The aggregator](aggregator.md)** → `aggregator_factory=` - - The optimizer — tune the reference merge/acceptance pipeline, or swap in your - own. - -- :material-vector-triangle: **[Parallelism](parallelism.md)** → `parallel=` - - Pluggable DP / TP methods, plus [sampling](sampling.md) for which rollout to - spend and [scheduling](duration-scheduling.md) for when. - -- :material-source-branch-sync: **[Async](async.md)** → `asynchronous=True` - - Barrier-free workers, a lag budget, and the - [staleness policies](staleness.md) that keep it safe. - -- :material-shield-lock: **[Governance](governance.md)** → `blast_radius=` - - L2 skills merge freely, L1 harnesses are oracle-gated, L0 is frozen — and - frozen *paths* for a directory. - -
- ---- - -## The central analogy - -| Model training | AgentDescent (parallel RSI) | -|---|---| -| parameter tensor θ | library of [`Evolvable`](data-model.md) artifacts | -| gradient *g* | [`Diff` + `EvidenceCard`](data-model.md) | -| parameter server | git-backed, version-vectored [`Ledger`](ledger.md) | -| optimizer step | [`Aggregator`](aggregator.md) merge decision | -| per-param adaptive LR (Adam) | per-artifact Beta-posterior test | -| staleness / decoupled PPO | [per-diff η + rebase re-verify](staleness.md) | -| partial rollout | [straggler detection](duration-scheduling.md) (`ResumeQueue`; resume not implemented) | -| EMA (weight averaging) | [`stable`/`dev` dual branch](ledger.md#two-branches-dev-and-stable) | -| training code (not self-modifiable) | [L0 frozen layer](governance.md) | - ---- - -## 30-second tour - -This demo command is available from the unreleased `main` checkout: - -```bash -git clone --branch main https://github.com/Birfy/agentdescent && cd agentdescent -pip install -e . -agentdescent demo # complete offline evolution loop -``` - -For the published v0.5.0 install and source-example workflow, see -[install and first run](install.md). Everything runnable, with the output each -one produces: [run everything](usage.md). - -No LLM or external service is required: the -[reference domain](orchestrator.md#why-a-synthetic-domain-exists-at-all) is a -fully deterministic keyword-router skill, so the entire parallel loop runs -in-process and is unit-tested — while still producing genuine diffs that -measurably improve a held-out metric. - -!!! note "Scope" - This is a **research reference implementation**, faithful to the design's - *mechanisms* and runnable end-to-end on a synthetic domain — not a - production system. See the design spec §2 for the honest, narrowed novelty - claim relative to FlashEvolve / SkillClaw / CoEvoSkills. diff --git a/docs/install.md b/docs/install.md index 0aa5017d..5df2f41e 100644 --- a/docs/install.md +++ b/docs/install.md @@ -1,162 +1,20 @@ -# Install and first run - -## Current `main`: packaged offline demo - -```bash -git clone --branch main https://github.com/Birfy/agentdescent && cd agentdescent -pip install -e . -agentdescent demo -``` - -The library supports Python ≥ 3.9 and current `main` installs NumPy for the -[`audit.ppi`](api.md) estimator. The packaged CLI demo runs offline and needs no -model API key: - -```bash -agentdescent demo -``` - -On current unreleased `main`, a successful run ends with output like: - -``` -held-out reward: 1.000 outcomes: {'committed': 1} -what it learned: rules.md -> 'COLUMN: amount' -``` - -After it finishes, try `agentdescent --help` to see the commands or continue to -the [quickstart](quickstart-skill.md) to connect a model. The library includes -[`evolve()`](evolution.md), the -[aggregator](aggregator.md), the [agent layer](agents.md), the -[data layer](dataloader.md), [directory evolution](directory-evolution.md). - -| extra | adds | for | -|---|---|---| -| `pip install -e ".[dev]"` | pytest | running the test suite in a contributor checkout | -| `pip install -e ".[docs]"` | MkDocs Material | building the docs from a contributor checkout | -| `pip install anthropic` | the Claude SDK | [`claude(...)`](agents.md) | -| `pip install openhands-ai` | OpenHands SDK (Python ≥ 3.12) | [`openhands(...)`](backends.md) | - -Nothing else is needed for an OpenAI-compatible endpoint — GLM, DeepSeek, a local -vLLM server — because [`openai_compatible`](agents.md) speaks HTTP directly. - -## Published v0.5.0 installation and source examples - -Install the stable PyPI package with: - -```bash -pip install agentdescent -``` - -The v0.5.0 release's documented offline demo uses research examples kept in the -source repository, outside the installed wheel. To run that example, clone the -tagged source and install the contributor tools: - -```bash -git clone --branch v0.5.0 https://github.com/Birfy/agentdescent && cd agentdescent -pip install -e ".[dev]" -``` - -Then run the source demo (no API key): - -```bash -python -m examples.run_demo -``` - -Examples are research artifacts kept **outside** the installed package (they -would otherwise squat the top-level `examples` name). This command runs the -merge-based loop and a fork baseline on the same budget over the -[reference domain](orchestrator.md), then prints the learning curve and the -comparison. This is the framework's central claim, reproducible in seconds: - -``` -round dev_acc stable commit fused stale confl oracle - 0 0.828 0.000 1 1 0 0 0 - 3 1.000 0.000 1 0 0 1 0 ← a contradiction dropped - 8 1.000 1.000 0 0 0 0 0 ← stable branch catches up - -AgentDescent (merge) held-out accuracy : 1.000 -Fork/archive best-fork accuracy : 0.379 -merge advantage : +0.621 -``` - -Two more that need nothing: - -```bash -python -m examples.skill_dir_evolution # evolve a skill DIRECTORY a real agent reads -python -m examples.efficiency # parallel scaling + async tail-hiding -``` - -The complete list — every demo, every algorithm port, and what each one prints — -is in [run everything](usage.md#1-run-the-demos). - -## First real run — with a model - -Point the provider layer at whatever you have. Credentials are read from the -environment at call time and never pass through code: - -```bash -export OPENAI_BASE_URL=https://api.deepseek.com # or GLM, vLLM, OpenAI itself -export OPENAI_API_KEY=sk-... -``` - -```python -from agentdescent import SingleSlot, evolve, openai_compatible, reflector, scorer, tasks_from -from agentdescent.dataloader import hf_rows - -rows = hf_rows("openai/gsm8k", config="main", split="train", limit=64) -model = openai_compatible(model="deepseek-v4-flash") - -result = evolve(tasks_from(rows, prompt="question", gold="answer"), scorer("last_number"), - run=lambda skill, task: model(f"{skill}\n\n{task.prompt}"), - propose=reflector(model), - strategy=SingleSlot(initial_value="You are a helpful assistant."), - rounds=8, n_workers=8, max_concurrency=8, held_out_frac=0.3) - -print(result.rendered) # the skill it learned -print(result.final_reward) # held-out reward -``` - -For Claude, `pip install anthropic` and use `claude(model="claude-haiku-4-5")` -instead — same call everywhere else. Full walkthrough: -[quickstart](quickstart-skill.md). - -!!! tip "Inspect a port with `--dry-run`" - All 20 algorithm ports print their configuration and return **with no model call - and no API key**. The eight benchmark-faithful ones return before touching data - as well; the eleven `MethodPolicy` ports build their policy first, so one on - a real benchmark downloads and caches its split during a dry run and says so. - - ```bash - python -m examples.ace.ace_context_evolution --dry-run - python -m examples.gepa.gepa_prompt_evolution --dry-run - ``` - -## Running the tests - -The suite is offline and deterministic — no network, no model API: - -```bash -pytest -q -``` - -CI runs it on Python 3.9, 3.10, 3.11 and 3.12 for every push and PR. - -## Building the docs - -```bash -pip install -e ".[docs]" -mkdocs serve # live preview at http://127.0.0.1:8000 -mkdocs build --strict # must pass with no warnings (CI enforces this) -python -m tools.gen_api_docs # regenerate the API reference after a signature change -``` - -## Where to go next - -| you want | go to | -|---|---| -| the shortest path from a dataset to a result | [Quickstart — a skill](quickstart-skill.md) | -| to evolve a folder a real agent reads | [Quickstart — a directory](quickstart-directory.md) | -| to understand why it is built this way | [Concepts](concepts.md) | -| every knob on the loop | [The `evolve` method](evolution.md) | -| a specific module | [Module map](modules.md) | -| a signature | [API reference](api.md) | +--- +description: Add AgentDescent to Claude Code, Codex, OpenCode or DeepSeek Harness, then ask your agent to improve a skill. +--- + +
+ +
HOME/ QUICKSTART
AGENTDESCENT × YOUR CODING AGENT

Tell your agent
what to improve.

Install the plugin, point it at a skill or prompt, and review its plan and diff right inside Claude Code, Codex, OpenCode or DeepSeek Harness.

Connect your agent ↓
◇ Python 3.10+ for MCP tools◇ Works with your agent CLI
Claude Code / AgentDescent
YOU

Improve my PDF audit skill against these examples.

✳
AGENTDESCENT · PLAN

12 cases · 4 workers · estimated call count ready for review

↗
AGENTDESCENT · SHOW

Proposed changes ready. Review the diff before applying.

+ +

Set it up once. Then just ask.

01

Install AgentDescent

Use current main for the latest host integrations. The MCP extra needs Python 3.10+.

git clone --branch main https://github.com/Birfy/agentdescent
+cd agentdescent
+pip install -e ".[mcp]"
02

Choose your agent

Pick the CLI you already use. Copy its setup command and restart or launch it as shown.

agentdescent install claude-code
+claude --plugin-dir ~/.agentdescent/plugins/claude-code

Start Claude Code with the plugin directory. In the session, /plugin lists it.

03

Ask for an improvement

Give it an artifact and examples. The agent checks the environment, shows a plan and call count, then asks before it runs or writes changes.

PASTE INSIDE YOUR AGENT

Improve the skill at ~/.claude/skills/pdf-audit against eval/cases.jsonl. Show me the plan and estimated calls before starting. Show the diff before applying.

+ +

You stay in control.

The agent uses the AgentDescent skill and MCP tools to prepare, run and inspect an evolution. Your real files change only after you approve applying the result.

Real model-backed runs need a configured provider key; agentdescent doctor reports what is missing. The offline demo below needs none.

01Doctor + planChecks setup, validates cases and quotes the call count.
02Start + statusRuns in the background and reports progress.
03Show + applyDisplays the diff; application is a separate approval.
+ +
◇

Try the engine offline

agentdescent demo runs a complete evolution without a model key. It is available on current main.

agentdescent demo
◇

No cases yet?

Point the agent at your file and ask it to draft 8–20 cases for you to review first. Good cases are how it knows what “better” means.

Read the full plugin guide ↗
◇

Need the details?

See host-specific checks, provider keys, CLI fallback for Python 3.9 and how to inspect a run.

Explore integration docs ↗
+
Using the published v0.5.0 package

pip install agentdescent installs the stable release. Its documented offline example lives in the source repository, outside the wheel. To run it, clone the v0.5.0 tag, install the development extra, and use python -m examples.run_demo. For the current plugin workflow above, use the main checkout.

Building these docs locally

From the repository checkout, run pip install -e ".[docs]", then mkdocs serve for a local preview or mkdocs build --strict for the production build.

+

Make the loop your own.

Explore strategies, policies and the Python API whenever you need more control.

Explore evolve() ↗
+ +
diff --git a/mkdocs.yml b/mkdocs.yml index f6adea12..71d75e48 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -153,6 +153,11 @@ markdown_extensions: class: mermaid format: !!python/name:pymdownx.superfences.fence_code_format +extra_css: + - assets/experience.css +extra_javascript: + - assets/experience.js + extra: social: - icon: fontawesome/brands/github