From 53baf45119e82c09abec2779cae08e7b5af875ab Mon Sep 17 00:00:00 2001 From: John Niche Date: Wed, 8 Apr 2026 13:40:09 -0300 Subject: [PATCH 1/8] =?UTF-8?q?fix(examples):=20reduce=20.ex-rail=5F=5Fseg?= =?UTF-8?q?=20min-width=20from=2056px=20to=2044px=20(=C2=A72)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Code quality review of Task 4 flagged that the 56px min-width floor was being silently defeated by flex-shrink: 17 segments × 56px + 72px ("all" anchor) + 34px (gaps) = 1058px minimum, but the parent .ct container has only 920px of content width (960px max-width minus 40px padding). Flex-shrink defaults to 1, so segments would compress below the floor anyway — defeating the whole point of min-width. Reducing to 44px gives 17×44 + 72 + 34 = 850px, which fits in 920px. 44px is also a reasonable touch target per WCAG 2.5.5 Level AAA. Spec §2: docs/superpowers/specs/2026-04-08-examples-page-overdrive-design.md --- landing/examples/index.html | 2 +- scripts/build_examples_gallery.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/landing/examples/index.html b/landing/examples/index.html index 5ceabda..036e571 100644 --- a/landing/examples/index.html +++ b/landing/examples/index.html @@ -43,7 +43,7 @@ .si{flex:1;background:var(--sf);border:1px solid var(--bd);border-radius:8px;padding:10px 14px;color:var(--tx);font-family:var(--font);font-size:14px;outline:none} .si:focus{border-color:var(--cy);box-shadow:0 0 0 2px rgba(34,211,238,0.12)}.si::placeholder{color:var(--ft)} .ex-rail{display:flex;gap:2px;height:40px;border-radius:8px;overflow:hidden;border:1px solid var(--bd);background:rgba(30,41,59,0.4)} -.ex-rail__seg{flex:var(--seg-weight,1) 1 0;min-width:56px;height:100%;display:flex;align-items:center;justify-content:center;gap:6px;font-family:var(--mono);font-size:12px;color:var(--dm);background:transparent;border:none;cursor:pointer;transition:background .15s,color .15s;position:relative;padding:0 8px;white-space:nowrap} +.ex-rail__seg{flex:var(--seg-weight,1) 1 0;min-width:44px;height:100%;display:flex;align-items:center;justify-content:center;gap:6px;font-family:var(--mono);font-size:12px;color:var(--dm);background:transparent;border:none;cursor:pointer;transition:background .15s,color .15s;position:relative;padding:0 8px;white-space:nowrap} .ex-rail__seg--all{flex:0 0 72px} .ex-rail__seg:hover{background:rgba(34,211,238,0.08);color:var(--tx)} .ex-rail__seg.on{background:rgba(34,211,238,0.12);color:var(--cy);box-shadow:inset 0 -2px 0 var(--exec-color)} diff --git a/scripts/build_examples_gallery.py b/scripts/build_examples_gallery.py index f9a3c3a..84856bf 100644 --- a/scripts/build_examples_gallery.py +++ b/scripts/build_examples_gallery.py @@ -287,7 +287,7 @@ def build_gallery(examples: list[dict]) -> str: .si{{flex:1;background:var(--sf);border:1px solid var(--bd);border-radius:8px;padding:10px 14px;color:var(--tx);font-family:var(--font);font-size:14px;outline:none}} .si:focus{{border-color:var(--cy);box-shadow:0 0 0 2px rgba(34,211,238,0.12)}}.si::placeholder{{color:var(--ft)}} .ex-rail{{display:flex;gap:2px;height:40px;border-radius:8px;overflow:hidden;border:1px solid var(--bd);background:rgba(30,41,59,0.4)}} -.ex-rail__seg{{flex:var(--seg-weight,1) 1 0;min-width:56px;height:100%;display:flex;align-items:center;justify-content:center;gap:6px;font-family:var(--mono);font-size:12px;color:var(--dm);background:transparent;border:none;cursor:pointer;transition:background .15s,color .15s;position:relative;padding:0 8px;white-space:nowrap}} +.ex-rail__seg{{flex:var(--seg-weight,1) 1 0;min-width:44px;height:100%;display:flex;align-items:center;justify-content:center;gap:6px;font-family:var(--mono);font-size:12px;color:var(--dm);background:transparent;border:none;cursor:pointer;transition:background .15s,color .15s;position:relative;padding:0 8px;white-space:nowrap}} .ex-rail__seg--all{{flex:0 0 72px}} .ex-rail__seg:hover{{background:rgba(34,211,238,0.08);color:var(--tx)}} .ex-rail__seg.on{{background:rgba(34,211,238,0.12);color:var(--cy);box-shadow:inset 0 -2px 0 var(--exec-color)}} From ffb88d7c48911daec27a361f0ba6dbab7e24c042 Mon Sep 17 00:00:00 2001 From: John Niche Date: Wed, 8 Apr 2026 16:14:27 -0300 Subject: [PATCH 2/8] =?UTF-8?q?feat(examples):=20search=20glyph,=20kbd=20h?= =?UTF-8?q?int,=20and=20#=20files=20match=20counter=20(=C2=A73)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wraps the search input with a leading ⌕ glyph and a trailing / keyboard shortcut hint. Adds a global keydown listener that focuses the search when / is pressed outside any input. Counter initial text finalized as '# N files match' to match the runtime format that Task 3's flt() already produces. Placeholder text lowered and clarified from 'Search examples…' to 'search by name or keyword…'. Adds autocomplete="off" to suppress browser autofill suggestions on the examples filter. Both the ⌕ glyph span and the / kbd hint are marked aria-hidden="true" per the decorative-atom convention. Spec §3: docs/superpowers/specs/2026-04-08-examples-page-overdrive-design.md --- landing/examples/index.html | 13 +++++++++++-- scripts/build_examples_gallery.py | 13 +++++++++++-- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/landing/examples/index.html b/landing/examples/index.html index 036e571..226af64 100644 --- a/landing/examples/index.html +++ b/landing/examples/index.html @@ -42,6 +42,10 @@ .ct{max-width:960px;margin:0 auto;padding:0 20px 16px;display:flex;flex-direction:column;gap:10px;position:sticky;top:52px;z-index:40;background:var(--bg);padding-top:10px} .si{flex:1;background:var(--sf);border:1px solid var(--bd);border-radius:8px;padding:10px 14px;color:var(--tx);font-family:var(--font);font-size:14px;outline:none} .si:focus{border-color:var(--cy);box-shadow:0 0 0 2px rgba(34,211,238,0.12)}.si::placeholder{color:var(--ft)} +.ex-search{position:relative;display:flex;align-items:center} +.ex-search__glyph{position:absolute;left:14px;color:var(--ft);font-size:14px;pointer-events:none} +.ex-search__kbd{position:absolute;right:12px;font-family:var(--mono);font-size:11px;color:var(--ft);background:rgba(100,116,139,0.15);padding:2px 6px;border-radius:4px;pointer-events:none} +.ex-search .si{padding-left:36px;padding-right:36px} .ex-rail{display:flex;gap:2px;height:40px;border-radius:8px;overflow:hidden;border:1px solid var(--bd);background:rgba(30,41,59,0.4)} .ex-rail__seg{flex:var(--seg-weight,1) 1 0;min-width:44px;height:100%;display:flex;align-items:center;justify-content:center;gap:6px;font-family:var(--mono);font-size:12px;color:var(--dm);background:transparent;border:none;cursor:pointer;transition:background .15s,color .15s;position:relative;padding:0 8px;white-space:nowrap} .ex-rail__seg--all{flex:0 0 72px} @@ -110,7 +114,11 @@

Selectools examples — 88 runnable Python scripts

- +
@@ -129,7 +137,7 @@

Selectools examples — 88 runnable Python scripts

-
88 examples
+
# 88 files match
01
Hello World — Your first Selectools agent
No API key needed. Runs entirely offline with the built-in LocalProvider.
No Key46L
@@ -233,6 +241,7 @@

Selectools examples — 88 runnable Python scripts

function syncPrompt(){const q=document.getElementById('si').value;document.getElementById('ex-grep').textContent=q?' | grep -i '+q:'';document.getElementById('ex-flags').textContent=ac==='all'?'':' --tags '+ac} function typeLine(target,text,perChar,done){let i=0;const tick=()=>{if(i<=text.length){target.textContent=text.slice(0,i);i++;setTimeout(tick,perChar)}else if(done){done()}};tick()} (function bootPrompt(){const cmd=document.getElementById('ex-cmd');if(!cmd)return;const reduced=window.matchMedia('(prefers-reduced-motion: reduce)').matches;if(reduced){cmd.textContent='ls examples/';syncPrompt();return}typeLine(cmd,'ls examples/',35,syncPrompt)})(); +document.addEventListener('keydown',(e)=>{if(e.key!=='/')return;const t=e.target;if(t&&(t.tagName==='INPUT'||t.tagName==='TEXTAREA'||t.isContentEditable))return;e.preventDefault();const si=document.getElementById('si');if(si)si.focus()}); diff --git a/scripts/build_examples_gallery.py b/scripts/build_examples_gallery.py index 84856bf..d8965c3 100644 --- a/scripts/build_examples_gallery.py +++ b/scripts/build_examples_gallery.py @@ -286,6 +286,10 @@ def build_gallery(examples: list[dict]) -> str: .ct{{max-width:960px;margin:0 auto;padding:0 20px 16px;display:flex;flex-direction:column;gap:10px;position:sticky;top:52px;z-index:40;background:var(--bg);padding-top:10px}} .si{{flex:1;background:var(--sf);border:1px solid var(--bd);border-radius:8px;padding:10px 14px;color:var(--tx);font-family:var(--font);font-size:14px;outline:none}} .si:focus{{border-color:var(--cy);box-shadow:0 0 0 2px rgba(34,211,238,0.12)}}.si::placeholder{{color:var(--ft)}} +.ex-search{{position:relative;display:flex;align-items:center}} +.ex-search__glyph{{position:absolute;left:14px;color:var(--ft);font-size:14px;pointer-events:none}} +.ex-search__kbd{{position:absolute;right:12px;font-family:var(--mono);font-size:11px;color:var(--ft);background:rgba(100,116,139,0.15);padding:2px 6px;border-radius:4px;pointer-events:none}} +.ex-search .si{{padding-left:36px;padding-right:36px}} .ex-rail{{display:flex;gap:2px;height:40px;border-radius:8px;overflow:hidden;border:1px solid var(--bd);background:rgba(30,41,59,0.4)}} .ex-rail__seg{{flex:var(--seg-weight,1) 1 0;min-width:44px;height:100%;display:flex;align-items:center;justify-content:center;gap:6px;font-family:var(--mono);font-size:12px;color:var(--dm);background:transparent;border:none;cursor:pointer;transition:background .15s,color .15s;position:relative;padding:0 8px;white-space:nowrap}} .ex-rail__seg--all{{flex:0 0 72px}} @@ -354,9 +358,13 @@ def build_gallery(examples: list[dict]) -> str:
- +
{chr(10).join(rail_segs)}
-
{total} examples
+
# {total} files match
{chr(10).join(cards)} @@ -373,6 +381,7 @@ def build_gallery(examples: list[dict]) -> str: function syncPrompt(){{const q=document.getElementById('si').value;document.getElementById('ex-grep').textContent=q?' | grep -i '+q:'';document.getElementById('ex-flags').textContent=ac==='all'?'':' --tags '+ac}} function typeLine(target,text,perChar,done){{let i=0;const tick=()=>{{if(i<=text.length){{target.textContent=text.slice(0,i);i++;setTimeout(tick,perChar)}}else if(done){{done()}}}};tick()}} (function bootPrompt(){{const cmd=document.getElementById('ex-cmd');if(!cmd)return;const reduced=window.matchMedia('(prefers-reduced-motion: reduce)').matches;if(reduced){{cmd.textContent='ls examples/';syncPrompt();return}}typeLine(cmd,'ls examples/',35,syncPrompt)}})(); +document.addEventListener('keydown',(e)=>{{if(e.key!=='/')return;const t=e.target;if(t&&(t.tagName==='INPUT'||t.tagName==='TEXTAREA'||t.isContentEditable))return;e.preventDefault();const si=document.getElementById('si');if(si)si.focus()}}); """ From 0a010fd572377dc5f6f99f14307752550f660d14 Mon Sep 17 00:00:00 2001 From: John Niche Date: Wed, 8 Apr 2026 16:19:40 -0300 Subject: [PATCH 3/8] =?UTF-8?q?feat(examples):=20card=20rows=20as=20ls=20-?= =?UTF-8?q?la=20grid=20columns=20(=C2=A74)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the flex-row .eh card header with a 7-column CSS Grid that mimics 'ls -la' output: number, permissions, size, key badge, filename (with NN_ prefix stripped), description, chevron. The first 30 rows get a 14ms-staggered fade-up enter animation via the .ex-row--enter class. Rows past index 29 render immediately to avoid a cascade-of-88 effect. Mobile collapses to 2-line layout with permissions column hidden. Rows are keyboard-accessible (Enter/Space) with aria-expanded synced via a surgical single-line addition to the existing toggle() function. Spec §4: docs/superpowers/specs/2026-04-08-examples-page-overdrive-design.md --- landing/examples/index.html | 205 ++++++++++++++++-------------- scripts/build_examples_gallery.py | 62 +++++---- 2 files changed, 146 insertions(+), 121 deletions(-) diff --git a/landing/examples/index.html b/landing/examples/index.html index 226af64..824c86f 100644 --- a/landing/examples/index.html +++ b/landing/examples/index.html @@ -60,15 +60,23 @@ .el{max-width:960px;margin:0 auto;padding:0 20px 60px;display:flex;flex-direction:column;gap:2px} .ec{border:1px solid var(--bd);border-radius:8px;overflow:hidden;background:var(--sf);background-image:var(--gr);transition:border-color .15s} .ec:hover{border-color:rgba(34,211,238,0.2)}.ec.op{border-color:rgba(34,211,238,0.3)} -.eh{display:flex;align-items:center;gap:14px;padding:14px 18px;cursor:pointer;user-select:none} -.en{font-family:var(--mono);font-size:12px;font-weight:500;color:var(--cy);min-width:24px;flex-shrink:0} -.ei{flex:1;min-width:0}.et{font-weight:600;font-size:13px;color:#fff;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} -.ed{font-size:12px;color:var(--dm);margin-top:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis} -.em{display:flex;gap:8px;align-items:center;flex-shrink:0} -.ek{font-family:var(--mono);font-size:10px;color:var(--ft);background:rgba(100,116,139,0.15);padding:2px 8px;border-radius:100px} -.enk{font-family:var(--mono);font-size:10px;color:var(--gn);background:rgba(34,197,94,0.1);padding:2px 8px;border-radius:100px} -.eln{font-family:var(--mono);font-size:10px;color:var(--ft)} -.ev{font-size:10px;color:var(--ft);transition:transform .2s}.ec.op .ev{transform:rotate(180deg)} +.ex-row{display:grid;grid-template-columns:32px 112px 54px 72px minmax(180px,1.5fr) minmax(0,3fr) 20px;align-items:center;gap:16px;padding:12px 18px;font-family:var(--mono);font-size:12px;cursor:pointer;user-select:none;transition:background-color .15s,border-left-color .15s;border-left:2px solid transparent} +.ex-row:hover{background:rgba(34,211,238,0.04);border-left-color:var(--cy)} +.ec.op .ex-row{background:rgba(34,211,238,0.06)} +.ex-row__num{color:var(--cy);font-weight:500} +.ex-row__perm{color:var(--ft)} +.ex-row__size{color:var(--ft);text-align:right} +.ex-row__key{font-size:10px;padding:2px 8px;border-radius:100px;text-align:center} +.ex-row__key--free{color:var(--gn);background:rgba(34,197,94,0.1)} +.ex-row__key--paid{color:var(--ft);background:rgba(100,116,139,0.15)} +.ex-row__file{color:var(--cy);overflow:hidden;text-overflow:ellipsis;white-space:nowrap} +.ex-row__desc{color:var(--tx);overflow:hidden;text-overflow:ellipsis;white-space:nowrap} +.ex-row__chev{font-size:10px;color:var(--ft);transition:transform 0.22s var(--exec-ease-soft);text-align:center} +.ec.op .ex-row__chev{transform:rotate(180deg)} +.ex-row--enter{animation:ex-row-in 0.35s var(--exec-ease-soft) both;animation-delay:calc(var(--row-index,0) * 14ms)} +@keyframes ex-row-in{from{opacity:0;transform:translateY(4px)}to{opacity:1;transform:none}} +@media(max-width:640px){.ex-row{grid-template-columns:32px 1fr 20px;gap:8px 12px}.ex-row__num{grid-column:1;grid-row:1 / 3;align-self:start}.ex-row__perm{display:none}.ex-row__file{grid-column:2;grid-row:1}.ex-row__chev{grid-column:3;grid-row:1 / 3;align-self:start}.ex-row__size{grid-column:2;grid-row:2;display:inline;margin-right:8px;color:var(--ft)}.ex-row__key{grid-column:2;grid-row:2;display:inline;margin-right:8px}.ex-row__desc{grid-column:2;grid-row:2;display:inline;color:var(--dm)}} +@media(prefers-reduced-motion:reduce){.ex-row--enter{animation:none}.ex-row__chev{transition-duration:0.01s}} .eb{padding:0 18px 18px}.eg{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:12px} .ec1{font-family:var(--mono);font-size:10px;padding:3px 8px;border-radius:4px;background:rgba(59,130,246,0.1);color:#93c5fd;text-decoration:none;transition:background .12s} a.ec1:hover{background:rgba(59,130,246,0.2);color:#bfdbfe} @@ -140,94 +148,94 @@

Selectools examples — 88 runnable Python scripts

# 88 files match
-
01
Hello World — Your first Selectools agent
No API key needed. Runs entirely offline with the built-in LocalProvider.
No Key46L
-
02
Search and Weather tools with ToolRegistry and @tool
No API key needed — runs with the built-in LocalProvider.
No Key69L
-
03
Pre-built Toolbox — 22 ready-made tools for files, data, text, datetime, and web
No API key needed for exploring tool schemas.
No Key205L
-
04
Multi-turn Conversation Memory with automatic context preservation
API Key89L
-
05
Cost Tracking — token counting, cost estimation, and usage summaries
API Key133L
-
06
Async Agent — arun(), concurrent agents, and FastAPI integration patterns
API Key194L
-
07
Streaming Tools — Generator-based progressive output for long-running operations
No Key354L
-
08
Streaming and Parallel Tool Execution — astream(), asyncio.gather, StreamChunk
API Key315L
-
09
Response Caching — InMemoryCache (LRU+TTL) and RedisCache for avoiding redundant LLM calls
API Key219L
-
10
Routing Mode — Agent selects a tool without executing it. Intent classification
API Key312L
-
11
Tool Usage Analytics — call counts, success rates, timing, cost attribution
API Key341L
-
12
Observability Hooks — lifecycle callbacks and tool validation at registration time
NOTE: For production observability (Langfuse, Datadog, OpenTelemetry), prefer the class-based AgentObserver protocol introduced in v0.14.0. It provides
No Key300L
-
13
Dynamic Tools — ToolLoader, plugin directories, hot-reload, runtime tool management
No Key220L
-
14
Basic RAG — document loading, chunking, embedding, vector search, and question answering
API Key157L
-
15
Semantic Search — pure embedding-based search with metadata filtering
API Key339L
-
16
Advanced RAG — PDFs, SQLite persistent storage, custom chunking, metadata filtering
API Key328L
-
17
Multi-Provider RAG Comparison — compare embeddings, stores, and chunk sizes across providers
Optional: ANTHROPIC_API_KEY, GOOGLE_API_KEY for cross-provider comparisons
API Key536L
-
18
Hybrid Search — BM25 keyword + vector semantic search with RRF/weighted fusion and reranking
API Key270L
-
19
Advanced Chunking — SemanticChunker (embedding-based) and ContextualChunker (LLM-enriched)
API Key224L
-
20
Customer Support Bot — multi-tool workflow combining search, ticketing, and escalation
API Key547L
-
21
Data Analysis Agent — data exploration, filtering, aggregation, and visualization tools
API Key820L
-
22
Ollama Local Model — run agents with fully local LLMs via Ollama. No cloud API needed
API Key253L
-
23
Structured Output — Get typed, validated responses from the LLM
Demonstrates: 1. Pydantic BaseModel as response_format
API Key243L
-
24
Execution Traces & Reasoning Visibility — See exactly what the agent did and why
Demonstrates: 1. result.trace with TraceStep timeline
API Key246L
-
25
Provider Fallback — Automatic failover between LLM providers
Demonstrates: 1. FallbackProvider with priority ordering
API Key250L
-
26
Batch Processing — Classify multiple requests concurrently
Demonstrates: 1. agent.batch() for sync concurrent processing
API Key263L
-
27
Tool Policy & Human-in-the-Loop — Control which tools the agent can execute
Demonstrates: 1. ToolPolicy with allow/review/deny rules
API Key308L
-
28
AgentObserver Protocol — structured lifecycle observability for production
Demonstrates: 1. Custom AgentObserver subclass with run_id/call_id correlation
API Key363L
-
29
Guardrails Engine
Demonstrates input and output guardrails for content validation, PII redaction, topic blocking, and format enforcement.
No Key155L
-
30
Audit Logging
Demonstrates JSONL audit logging with privacy controls and daily file rotation.
No Key88L
-
31
Tool Output Screening
Demonstrates prompt injection detection in tool outputs, both per-tool and global screening.
API Key109L
-
32
Coherence Checking
Demonstrates LLM-based intent verification that catches tool calls diverging from the user's original request (prompt injection defence).
API Key128L
-
33
Persistent Sessions — Save and restore conversation memory across agent instances
Demonstrates JsonFileSessionStore: the agent's conversation history is persisted to disk and restored when a new agent is created with the same session_id.
No Key71L
-
34
Summarize-on-Trim — Automatically summarize old messages when memory is trimmed
When the conversation exceeds max_messages, the oldest messages are removed. With summarize_on_trim=True the agent asks an LLM to condense them into a
No Key70L
-
35
Entity Memory — Extract and track named entities across conversation turns
EntityMemory merges entities into a deduplicated registry and builds a context block for the system prompt. This example manually feeds entities to demonstrate
No Key78L
-
36
Knowledge Graph Memory — Track relationship triples across conversation turns
KnowledgeGraphMemory stores subject-relation-object triples in a TripleStore. Relevant triples are queried each turn and injected into the system prompt.
No Key81L
-
37
Knowledge Memory — Persistent cross-session facts with daily logs
KnowledgeMemory stores daily log entries and persistent facts in MEMORY.md. When configured on an agent, a ``remember`` tool is auto-registered and the
No Key79L
-
38
Example 38 — Terminal Tools and Stop Conditions
Demonstrates how to stop the agent loop after a specific tool fires, without making another LLM call. Two mechanisms:
No Key139L
-
39
Built-in Eval Framework
==================================== Evaluate your agent's accuracy, tool use, latency, cost, and safety
No Key166L
-
40
Advanced Eval — A/B Testing, LLM Judges, Snapshots, Badges
====================================================================== Showcases advanced eval features:
No Key188L
-
41
MCP Client — Connect to MCP Tool Servers
===================================================== Use tools from any MCP-compatible server in your selectools agent.
No Key127L
-
42
MCP Server — Expose Selectools Tools as MCP
======================================================== Turn any selectools @tool function into an MCP-compliant server.
API Key80L
-
43
Token Budget Per Run — stop agents before they burn money
Demonstrates: - max_total_tokens: hard limit on cumulative tokens
API Key165L
-
44
Agent Cancellation — cooperative stopping from any thread
Demonstrates: - CancellationToken for cooperative cancellation
API Key203L
-
45
Per-Tool Approval Gate — require human approval for dangerous tools
Demonstrates: - @tool(requires_approval=True) decorator flag
API Key212L
-
46
SimpleStepObserver — single callback for all agent events
Demonstrates: - SimpleStepObserver routes 31 events to one function
API Key178L
-
47
Token Estimation — estimate costs before running an agent
Demonstrates: - estimate_tokens() for single strings
API Key136L
-
48
Model Switching — use different models per iteration
Demonstrates: - model_selector callback on AgentConfig
API Key202L
-
49
Knowledge Memory Stores — persistent knowledge with importance and TTL
Demonstrates: - KnowledgeMemory with SQLiteKnowledgeStore backend
API Key188L
-
50
Reasoning Strategies — ReAct, Chain-of-Thought, and Plan-Then-Act
Demonstrates: - reasoning_strategy="react" — Thought → Action → Observation cycle
API Key132L
-
51
Tool Result Caching — avoid re-executing expensive tools
Demonstrates: - @tool(cacheable=True) — cache tool results by name + args
API Key93L
-
52
Semantic Cache — serve LLM responses for similar (not just identical) queries
Demonstrates: - SemanticCache as a drop-in replacement for InMemoryCache
API Key204L
-
53
Prompt Compression — prevent context-window overflow in long conversations
Demonstrates: - compress_context=True — enable proactive context compression
API Key264L
-
54
Conversation Branching — fork conversation history for A/B exploration
Demonstrates: - ConversationMemory.branch() — snapshot memory for safe experimentation
API Key203L
-
55
Linear AgentGraph pipeline
Demonstrates a simple 3-node linear graph: planner → writer → reviewer → END
No Key64L
-
56
Parallel fan-out with AgentGraph
Demonstrates parallel execution of multiple agents with state merging: entry → [researcher_a, researcher_b, researcher_c] → summarizer → END
No Key66L
-
57
Conditional routing with AgentGraph
Demonstrates conditional edges with path_map validation: drafter → router → (revise | publish) → END
No Key71L
-
58
Human-in-the-loop with AgentGraph
Demonstrates generator nodes with yield InterruptRequest: - Graph pauses at reviewer node
No Key109L
-
59
Checkpointing with AgentGraph
Demonstrates durable mid-graph persistence using FileCheckpointStore: - Save checkpoints after each node
No Key107L
-
60
SupervisorAgent with multiple coordination strategies
Demonstrates all four supervisor strategies: - plan_and_execute: LLM generates a plan, then executes each step
No Key124L
-
61
Nested subgraphs with AgentGraph
Demonstrates SubgraphNode — an AgentGraph embedded as a node in another graph. Uses input_map and output_map for explicit state key translation.
No Key84L
-
62
Loading an Agent from YAML config
Demonstrates the structured AgentConfig workflow (v0.19.0): - Write a YAML config file describing the agent
No Key101L
-
63
Agent Templates
Demonstrates the template system (v0.19.0): - List available built-in templates
No Key165L
-
64
Serving an Agent over HTTP
Demonstrates the `selectools serve` pattern (v0.19.0): - Create an agent with tools
No Key183L
-
65
Tool Composition with compose()
Demonstrates composing multiple tools into a single composite tool (v0.19.0): - Define individual tools with @tool()
No Key122L
-
66
Streaming Pipeline with astream()
Demonstrates pipeline streaming (v0.19.0): - Build a multi-step pipeline with @step
API Key132L
-
67
Type-Safe Pipeline Contracts
Demonstrates type-safe step contracts in pipelines (v0.19.0): - Steps infer input/output types from type hints
API Key137L
-
68
PostgresCheckpointStore for AgentGraph
Demonstrates using PostgreSQL as a checkpoint backend (v0.19.0): - Create a PostgresCheckpointStore with a connection string
API Key158L
-
69
Trace Storage and Querying
Demonstrates saving and querying agent traces (v0.19.0): - InMemoryTraceStore for development
No Key369L
-
70
PlanAndExecuteAgent
The planner Agent generates a JSON execution plan. Executor agents handle each step in sequence. Results are aggregated into a final output.
No Key107L
-
71
ReflectiveAgent
The actor Agent produces an initial draft. The critic Agent evaluates it and provides feedback. The actor revises based on the critique. This cycle repeats
No Key107L
-
72
DebateAgent
Multiple agents argue opposing positions over max_rounds rounds. Each agent sees the prior round transcript so they can respond to each other. A judge
No Key123L
-
73
TeamLeadAgent
The lead Agent generates a subtask plan and delegates to team members. Three delegation strategies are demonstrated:
No Key199L
-
74
trace_to_html — HTML Trace Viewer
Renders an AgentTrace as a standalone HTML waterfall timeline. No external dependencies — the output is a single self-contained HTML file.
No Key66L
-
75
Stability Markers — @stable, @beta, @deprecated
The stability module provides three decorators for annotating the public API stability of any class or function.
API Key112L
-
76
Visual Agent Builder (v0.20.0)
topology in a browser, generate Python or YAML, copy or download. Start the builder with one command (no config file needed):
API Key39L
-
77
FAISS Vector Store -- fast local similarity search with persistence
No API key needed. Uses FAISS (Facebook AI Similarity Search) for high-performance local vector search. Supports save/load to disk.
API Key49L
-
78
Qdrant Vector Store -- production vector search with metadata filtering
Qdrant is a high-performance vector database with advanced filtering. This example shows the API pattern (requires a running Qdrant server).
API Key46L
-
79
pgvector Store -- PostgreSQL-native vector search
Use your existing PostgreSQL database for vector similarity search. No additional database infrastructure needed.
API Key43L
-
80
Document Loaders -- CSV, JSON, HTML, URL loading
No API key needed. Demonstrates all new document loader methods.
API Key76L
-
81
Multimodal Messages -- send images to your agent
No API key needed for this demo. Shows how to create messages with images for vision-enabled models (GPT-4o, Claude 3.5, Gemini).
API Key57L
-
82
Code Execution Tools -- run Python and shell commands from agents
No API key needed. Demonstrates the execute_python and execute_shell tools. WARNING: These tools execute code on your local machine. Do not use with
API Key64L
-
83
Web Search Tools -- search the web and scrape URLs
No API key needed. Uses DuckDuckGo for search (no rate limits for moderate use).
API Key52L
-
84
GitHub Tools -- search repos, read files, list issues from agents
No API key needed (optional GITHUB_TOKEN increases rate limit from 60 to 5000/hr). Read-only operations only.
API Key53L
-
85
Database Query Tools -- SQL queries from agents (read-only)
No API key needed. Creates a sample SQLite database and queries it. Also supports PostgreSQL with psycopg2.
API Key88L
-
86
Azure OpenAI Provider -- use OpenAI models via Azure endpoints
Requires: AZURE_OPENAI_ENDPOINT and AZURE_OPENAI_API_KEY env vars.
API Key52L
-
87
OpenTelemetry Observer -- send agent traces to Datadog, Jaeger, Grafana
Maps selectools observer events to OTel GenAI semantic convention spans. Works with any OTel-compatible backend.
API Key56L
-
88
Langfuse Observer -- send agent traces to Langfuse for LLM observability
Langfuse is the most popular open-source LLM observability platform. Traces include LLM calls, tool executions, costs, and latencies.
API Key59L
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/scripts/build_examples_gallery.py b/scripts/build_examples_gallery.py index d8965c3..e65670a 100644 --- a/scripts/build_examples_gallery.py +++ b/scripts/build_examples_gallery.py @@ -199,7 +199,6 @@ def build_gallery(examples: list[dict]) -> str: cards = [] for ex in examples: cats_str = " ".join(ex["categories"]) - # Category tags link to their doc pages cat_parts = [] for c in ex["categories"]: label = c.replace("-", " ").title() @@ -208,30 +207,38 @@ def build_gallery(examples: list[dict]) -> str: else: cat_parts.append(f'{label}') cats_html = "".join(cat_parts) - key_badge = ( - 'API Key' - if ex["needs_key"] - else 'No Key' - ) + key_class = "ex-row__key--paid" if ex["needs_key"] else "ex-row__key--free" + key_label = "api-key" if ex["needs_key"] else "no-key" graph_btn = "" if ex["has_graph"]: graph_btn = f'Open in Builder' - # Doc link — use first category with a doc page doc_btn = "" for c in ex["categories"]: if c in CAT_DOCS: doc_btn = f'Docs' break + # Strip the leading "NN_" from the displayed filename (column 1 already shows the number) + display_file = re.sub(r"^\d+_", "", ex["file"]) + + # Per-row enter animation: only the first 30 rows get .ex-row--enter + row_index = ex["num"] - 1 + enter_class = " ex-row--enter" if row_index < 30 else "" + enter_style = f' style="--row-index:{row_index}"' if row_index < 30 else "" + cards.append( f'
' - f'
' - f'
{ex["num"]:02d}
' - f'
{html.escape(ex["title"])}
' - f'
{html.escape(ex["desc"])}
' - f'
{key_badge}{ex["lines"]}L
' - f'
' + f'" f'