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]"
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 - -
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 agentdescentAgentDescent 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 ↗See the plugin workflow as it appears inside Claude Code, Codex, OpenCode or DeepSeek Harness.
Change the path to personalize the sample conversation.
Illustrative browser demo. No agent runs, model calls or file changes.
One engine, multiple representations. The key space determines which concurrent edits can merge.
Start from a prompt and let the loop search for a stronger version against your tasks.
Read the prompt quickstart ↗You are a helpful assistant. + ++ Respond with only the requested answer. ++ Omit extra explanation and restatement.
No API key needed for the current main branch’s offline demo.
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 ↓Improve my PDF audit skill against these examples.
12 cases · 4 workers · estimated call count ready for review
Proposed changes ready. Review the diff before applying.
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]"
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.
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.
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.
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.
agentdescent demo runs a complete evolution without a model key. It is available on current main.
agentdescent demoPoint 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 ↗See host-specific checks, provider keys, CLI fallback for Python 3.9 and how to inspect a run.
Explore integration docs ↗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.
From the repository checkout, run pip install -e ".[docs]", then mkdocs serve for a local preview or mkdocs build --strict for the production build.
Explore strategies, policies and the Python API whenever you need more control.