genai-tk · diff

git:20261013.980e7e1 to git:20261013.09dd77b

150 added, 259 removed. Audit A to A.

---
name: genai-tk
- description: Build GenAI and agentic applications with the genai-tk toolkit (https://github.com/tclatos/genai-tk) — a YAML-driven wrapper over LangChain, LangGraph, and 100+ LLM providers. Use this skill whenever the user mentions genai-tk, genai_tk, the GenAI Toolkit, `cli init`, `LangchainAgent`, `get_llm`/`get_embeddings`, `RetrieverFactory`/`ManagedRetriever`, the four bundled agent frameworks (ReAct, Deep, Deer-flow, SmolAgents), the OpenSandbox Docker integration, the `model_id@provider` identifier format, the `global_config()`/`OmegaConfig` system with `app_conf.yaml` and `:merge`, BAML structured extraction, SkillsMiddleware, writing or editing the toolkit's YAML profiles (langchain.yaml, deerflow.yaml, llm.yaml, retrievers.yaml), composing retrievers (vector/bm25/ensemble/reranked/pg_hybrid/zero_entropy), or extending the CLI with `CliTopCommand`. Trigger even when the user only says "the toolkit" in context.
+ description: >
+ Build GenAI and agentic apps with genai-tk (tclatos/genai-tk), a YAML-driven IoC toolkit over LangChain,
+ DeepAgents, DeerFlow, and Prefect. Use this skill whenever the user mentions genai-tk, genai_tk, `cli init`,
+ `cli agents run`, `LangchainAgent`, `create_harness`, `get_llm`, `global_config()`, `model_id@provider`,
+ `agents:`/`agent_defaults:` profiles, `RetrieverFactory`, `cli workflow`, or BAML extraction. Also trigger
+ for app_conf.yaml, GENAITK_PROFILE, CodeAct, OpenSandbox, decision models, or "the toolkit".
---
# genai-tk — GenAI & Agentic Toolkit
- `genai-tk` (https://github.com/tclatos/genai-tk) is a Python toolkit that wraps LangChain, LangGraph, and 100+ LLM providers into a YAML-driven, configuration-first architecture. It's not a framework you build *into* — it's an inversion-of-control layer where **profiles in YAML** drive **factories** that produce LangChain runtime objects (LLMs, embeddings, retrievers, agents).
-
- The mental model:
+ [genai-tk](https://github.com/tclatos/genai-tk) is a Python 3.12+ toolkit where **YAML config drives everything**:
+ LLM providers, agent profiles, retrievers, workflows, and CLI commands are declared in `config/*.yaml` and
+ resolved at runtime through an Inversion-of-Control registry (`ImportResolver`). You extend it by adding YAML
+ entries that point at dotted Python paths, not by editing the library.
```text
- config/*.yaml ──► global_config() ──► Factory ──► LangChain object ──► your code
+ config/app_conf.yaml ─► global_config() ─► ImportResolver ─► factories / harness ─► LangChain objects
```
+ > Verified against upstream commit `7fbd7a3` (2026-10-12). The toolkit moves fast and **several upstream docs lag
+ > the code** (see "Upstream doc drift" below). When docs and code disagree, trust the code.
+
## Quick Reference
| Topic | Reference |
|-------|-----------|
- | Agent frameworks: ReAct, Deep, Deer-flow, SmolAgents — profiles, tools, middleware, MCP, sandbox, skills | [agents.md](references/agents.md) |
- | RAG: `RetrieverFactory`, `ManagedRetriever`, the six retriever types, ingestion | [rag.md](references/rag.md) |
- | Configuration: `global_config()`, `app_conf.yaml`, `:merge`, environments, `model_id@provider` | [configuration.md](references/configuration.md) |
- | CLI: `cli init`, command groups, extending the CLI with `CliTopCommand` | [cli-and-init.md](references/cli-and-init.md) |
- | BAML structured extraction with `BamlStructuredProcessor` | [baml-structured.md](references/baml-structured.md) |
-
- ## Installation
-
- The toolkit is installed via `uv` and is **not on PyPI** — install from the GitHub repo:
-
- ```bash
- # Add to existing project
- uv add git+https://github.com/tclatos/genai-tk@main
-
- # With extras (postgres, browser, evals)
- uv add "genai-tk[extra] @ git+https://github.com/tclatos/genai-tk@main"
-
- # Development (clone & edit)
- git clone https://github.com/tclatos/genai-tk.git && cd genai-tk
- uv sync # core + dev
- uv sync --all-groups # + postgres, browser, evals
- ```
-
- After install, scaffold a project:
+ | Install, extras, `cli init`, full CLI command tree, `CliTopCommand`, `cli skills`, house conventions | [cli-and-init.md](references/cli-and-init.md) |
+ | `app_conf.yaml`, `:merge`, `:profiles`, `GENAITK_PROFILE`, typed config access, IoC | [configuration.md](references/configuration.md) |
+ | `get_llm` / `get_embeddings`, `model_id@provider`, providers.yaml, reasoning effort, routing, decision models | [models.md](references/models.md) |
+ | Agent profiles, harness layer, tools, middlewares, skills, sandbox, MCP, DeerFlow, CodeAct, trajectories | [agents.md](references/agents.md) |
+ | `RetrieverFactory`, `ManagedRetriever`, embeddings stores, chunkers, `cli rag`, RAG as a tool | [rag.md](references/rag.md) |
+ | YAML workflows, Prefect, ingest routing, markdownize converters | [workflows.md](references/workflows.md) |
+ | BAML structured extraction: `BamlStructuredProcessor`, `baml_invoke`, `cli baml` | [baml-structured.md](references/baml-structured.md) |
- ```bash
- uv run cli init --name "My AI Project" # full scaffold (recommended)
- uv run cli init --minimal # config + Makefile only
- uv run cli init --deer-flow # also clone Deer-flow backend
- uv sync
- ```
+ ## Core Workflow
- `cli init` creates `config/`, `Makefile`, a Python package with example CLI commands and an LCEL chain, an `AGENTS.md`, and `.github/copilot-instructions.md`. See [cli-and-init.md](references/cli-and-init.md) for the full file inventory.
+ ### 1. Install and scaffold
- API keys go in `.env` at the project root (auto-loaded):
+ genai-tk is **not on PyPI**. Install from git with `uv`, then scaffold:
```bash
- OPENAI_API_KEY=sk-...
- ANTHROPIC_API_KEY=...
- GROQ_API_KEY=...
- TAVILY_API_KEY=... # for web search
+ uv init my-app && cd my-app
+ uv add "genai-tk @ git+https://github.com/tclatos/genai-tk@main"
+ uv run cli init --name "My Agent App" # scaffolds config/, skills/, justfile; runs uv sync
+ uv run cli init --extra harnessing --extra browser # also install DeepAgents/DeerFlow + Playwright
+ just run # uv run cli agent chat
```
- ## The four pillars
-
- ### 1. LLM & Embeddings factories
+ Extras: `harnessing` (deepagents, DeerFlow, OpenSandbox), `browser`, `nlp`, `postgres`, `streamlit`, `baml`,
+ `chromadb`, `docling`, `monitoring`, and `all` (everything except `monitoring`). Put API keys in `.env`
+ (auto-loaded, plus `~/.env` for the CLI). Run `uv run cli info doctor` as a pre-flight check.
- Models are referenced as `model_id@provider`. The `model_id` is a short alias declared in `config/providers/llm.yaml`; the provider is one of `openai`, `openrouter`, `groq`, `ollama`, `fake`, etc. The toolkit auto-resolves model capabilities from a built-in `models.dev` database covering 1000+ models.
+ ### 2. Call models
```python
- from genai_tk.core.llm_factory import get_llm
- from genai_tk.core.embeddings_factory import get_embeddings
-
- llm = get_llm() # default from baseline.yaml
- llm = get_llm("gpt41mini@openai") # explicit alias
- llm = get_llm("fast_model") # named tag from baseline.yaml
- llm = get_llm("gpt-4o-mini") # raw model name — fuzzy resolved
- llm = get_llm("parrot_local@fake") # fake model — no API key, returns input
-
- # kwargs forward to the underlying ChatModel
- llm = get_llm("gpt41mini@openai", temperature=0.7, streaming=True, json_mode=True)
+ from genai_tk.core.factories import get_llm, get_embeddings
- # Reasoning/thinking models
- llm = get_llm("o3@openai", reasoning=True)
+ llm = get_llm() # llm.models.default from the active profile
+ llm = get_llm("fast_model") # a tag under llm.models
+ llm = get_llm("gpt-4o-mini@openai") # model_id@provider (resolved via models.dev)
+ llm = get_llm("parrot_local@fake") # offline fake model, no API key
+ llm = get_llm("o3 (high)@openai") # inline reasoning effort
+ llm = get_llm("claude-haiku@openrouter:speed") # gateway routing strategy
+ llm = get_llm("gpt-4o-mini@openai", streaming=True, json_mode=True, cache="sqlite")
- embeddings = get_embeddings() # default
- embeddings = get_embeddings("ada_002@openai") # explicit
- vectors = embeddings.embed_documents(["doc 1", "doc 2"])
+ embeddings = get_embeddings() # embeddings.models.default
```
- The returned object is a regular LangChain `BaseChatModel` / `Embeddings`, so it composes with everything else in the LC ecosystem (LCEL, prompts, output parsers, LangGraph nodes, etc.).
+ Both return plain LangChain `BaseChatModel` / `Embeddings` objects. CLI: `cli core llm -i "hello" -m parrot_local@fake`,
+ `cli info models`, `cli info llm-profile <id>`. Details in [models.md](references/models.md).
- `get_llm()` accepts `cache="sqlite"`, `"memory"`, or `"no_cache"` to override the global cache. Defaults are set in `baseline.yaml` (`llm.cache: sqlite`, `llm.cache_path: data/llm_cache/langchain.db`).
+ ### 3. Define an agent in YAML, run it anywhere
- To list every model the toolkit knows about:
+ Profiles live under a top-level `agents:` **dict keyed by slug**, in `config/agents.yaml` or `config/agents/*.yaml`.
+ `agent_defaults:` supplies fallbacks for LangChain profiles.
- ```bash
- cli info models # all declared + db-discovered
- cli info llm-profile gpt41mini@openai # exact match
- cli info llm-profile gpt-4o # fuzzy match
- cli info config # show resolved config + API key status
+ ```yaml
+ # config/agents.yaml
+ agent_defaults:
+ type: react
+ default_profile: research
+ agents:
+ research:
+ harness: langchain # langchain (default) | deerflow
+ name: "Research"
+ type: deep # react | deep | custom
+ llm: gpt-4o-mini@openai
+ system_prompt: "You are an expert researcher. Cite sources."
+ tools:
+ - genai_tk.agents.tools.langchain.search_tools_factory.create_search_function:
+ verbose: false
+ mcp_servers: [filesystem] # names from mcpServers: in mcp_servers.yaml
+ skill_directories: ["${paths.project}/skills"]
+ enable_planning: true
+ enable_file_system: true
+ checkpointer: {type: memory} # none | memory | class
```
- ### 2. Agents — four frameworks, one profile system
-
- | Framework | Best for | Profile location |
- |-----------|----------|------------------|
- | **ReAct** (LangChain) | General tasks, tool use | `config/agents/langchain.yaml` (`type: react`) |
- | **Deep** (LangChain + `deepagents`) | Multi-step planning, subagents, sandbox | `config/agents/langchain.yaml` (`type: deep`) |
- | **Deer-flow** (ByteDance, embedded) | Deep web research, native search | `config/agents/deerflow.yaml` |
- | **SmolAgents** (HuggingFace) | Code-first automation | invoked via `cli agents smolagents` |
-
- All four share the same LLM factory, MCP server registry, sandbox config, and skills directories. The unified entry point for LangChain agents is `LangchainAgent`:
-
```python
from genai_tk.agents.langchain import LangchainAgent
- # From a YAML profile
- agent = LangchainAgent("Research")
- result = agent.run("Summarise recent AI news")
-
- # Async / streaming
- result = await agent.arun("Explain RAG")
- async for chunk in agent.astream("Tell me a story"):
- print(chunk, end="", flush=True)
-
- # Ad-hoc agent (no profile needed when llm is given)
- agent = LangchainAgent(llm="gpt41mini@openai", tools=[my_tool])
- ```
-
- A profile in `langchain.yaml`:
-
- ```yaml
- langchain_agents:
- default_profile: "Research"
- profiles:
- - name: "Research"
- type: deep
- llm: gpt_41@openai
- enable_planning: true
- tools:
- - spec: web_search
- config: { provider: serper }
- mcp_servers: [tavily-mcp]
- skills:
- directories:
- - ${paths.project}/skills
- backend:
- type: aio_sandbox # optional Docker sandbox
- checkpointer:
- type: memory # memory | postgres | sqlite
+ agent = LangchainAgent("research", llm="claude-haiku@openrouter") # slug or display name, + overrides
+ print(agent.run("Summarise this week's AI news"))
```
- CLI equivalents:
-
```bash
- cli agents langchain --list # show profiles
- cli agents langchain -p Research --chat # interactive
- cli agents langchain -p Research "Query" # one-shot
- cli agents langchain --sandbox docker -p Research "..." # sandboxed exec
- cli agents deerflow --chat # Deer-flow
- cli agents smolagents --executor docker "..." # code-first
+ uv run cli agents list
+ uv run cli agents run research "Summarise this week's AI news"
+ uv run cli agents run research --chat
```
- For the full agent reference — type semantics, middlewares, tool specs, MCP wiring, sandbox setup, skill loading — read [agents.md](references/agents.md).
-
- ### 3. RAG — `RetrieverFactory` + `ManagedRetriever`
-
- The RAG layer is built around two abstractions:
-
- - **`RetrieverFactory.create(tag)`** — reads `retrievers.<tag>` from YAML, returns a `ManagedRetriever`
- - **`ManagedRetriever`** — async-first wrapper with `aquery`, `aadd_documents`, `adelete_store`, `get_stats`
-
- Six retriever types compose freely under the `retrievers:` YAML key:
-
- | Type | Purpose |
- |------|---------|
- | `vector` | Dense similarity (Chroma, InMemory, PgVector) |
- | `bm25` | Sparse keyword (`bm25s` library, persisted to disk) |
- | `ensemble` | Reciprocal-rank fusion of N other retrievers |
- | `reranked` | Wraps another retriever with embeddings / Cohere / cross-encoder reranking |
- | `pg_hybrid` | PostgreSQL pgvector + tsvector full-text in a single query |
- | `zero_entropy` | Read-only ZeroEntropy SDK retriever |
-
- ```python
- from genai_tk.core.retriever_factory import RetrieverFactory
-
- retriever = RetrieverFactory.create("hybrid_with_rerank") # tag from YAML
- docs = await retriever.aquery("question", k=5)
- await retriever.aadd_documents(documents) # if has_store
- ```
+ For a harness-agnostic API (LangChain and DeerFlow behind one event stream), use
+ `genai_tk.agents.harness.create_harness("research")`. See [agents.md](references/agents.md).
- A composed YAML config:
+ ### 4. Add RAG, workflows, or structured extraction
```yaml
+ embeddings_store:
+ chroma:
+ backend: genai_tk.core.vector_backends.ChromaBackend
+ embeddings: default
+ config: {storage: "${paths.data_root}/vector_store"}
retrievers:
- my_vec:
- type: vector
- embeddings_store: chroma_indexed
- top_k: 8
- bm25_local:
- type: bm25
- k: 8
- preprocessing: spacy
- hybrid:
- type: ensemble
- retrievers:
- - { ref: my_vec, weight: 0.7 }
- - { ref: bm25_local, weight: 0.3 }
- hybrid_with_rerank:
- type: reranked
- retriever: hybrid
- reranker: embeddings
- top_k: 4
- fetch_k: 12
+ docs: {type: genai_tk.core.retrievers.VectorRetriever, embeddings_store: chroma, top_k: 4}
```
- CLI:
-
```bash
- cli rag list-retrievers # show tags
- cli rag add-files my_vec ./docs/ # ingest
- cli rag query my_vec "What does the doc say about X?"
+ uv run cli rag add-files ./docs -r docs -p "**/*.md"
+ uv run cli rag query "What does the doc say about X?" -r docs
+ uv run cli workflow run markdownize/fast --set sources=./inbox --set md_output_dir=./data/md
+ uv run cli baml run ExtractResume -i "John Smith; 10 years Python" # a function from your baml_src/
```
- For the full RAG reference — every retriever type's full schema, the document store separation, ingestion semantics, PgHybrid setup, and using retrievers as agent tools — read [rag.md](references/rag.md).
-
- ### 4. Configuration — `global_config()` + `app_conf.yaml`
-
- The config system uses [OmegaConf](https://omegaconf.readthedocs.io/) with auto-discovery: on import, `global_config()` walks up from the current working directory until it finds `config/app_conf.yaml`. **This means notebooks, subdirectories, and deployed containers all work without setup.**
-
- ```python
- from genai_tk.utils.config_mngr import global_config
-
- cfg = global_config()
- default_llm = cfg.get("llm.default") # str
- top_k = cfg.get("retrievers.my_vec.top_k", 4) # with default
- agent_profiles = cfg.get_dict("langchain_agents.profiles")
- ```
+ ## Configuration in One Minute
- `app_conf.yaml` is the entry point. It declares a `:merge` list of YAML files that are deep-merged in order (later wins):
+ `config/app_conf.yaml` is the root. It is loaded from `config/app_conf.yaml` **relative to the current working
+ directory** (it does not walk up parent directories), so run commands from the project root.
```yaml
- default_config: ${oc.env:BLUEPRINT_CONFIG,baseline}
-
- :merge:
- - ${paths.config}/baseline.yaml
- - ${paths.config}/providers/llm.yaml
- - ${paths.config}/providers/embeddings.yaml
- - ${paths.config}/overrides.yaml
- - ${paths.config}/mcp_servers.yaml
-
- :env:
- LOGURU_LEVEL: INFO
-
+ profile: ${oc.env:GENAITK_PROFILE,local}
paths:
project: ${oc.env:PWD}
config: ${paths.project}/config
data_root: ${paths.project}/data
+ :merge: ["**/*.yaml", "!demos/**", "!examples/agents/**"] # gitignore-style globs under config/
+ :profiles:
+ local:
+ llm: {models: {default: gpt-4o-mini@openai, fake: parrot_local@fake}, cache: sqlite}
+ embeddings: {models: {default: embeddings_768@fake}}
+ :env: {LOGURU_LEVEL: INFO}
```
- Switch named environments without touching code: `BLUEPRINT_CONFIG=production` (env var) or `cfg.select_config("production")` (Python). Env vars in `${oc.env:VAR,default}` come from `.env`.
-
- For the full configuration reference — directive semantics, override patterns, computed paths, environment switching — read [configuration.md](references/configuration.md).
-
- ## When to use what — a decision guide
-
- | You want to… | Reach for | Doc |
- |--------------|-----------|-----|
- | Call an LLM with a one-line config swap | `get_llm("alias@provider")` | `core.md` (in repo) |
- | Build a tool-using agent | `LangchainAgent("ProfileName")` (`type: react`) | [agents.md](references/agents.md) |
- | Plan + delegate to subagents | `type: deep` profile + Docker sandbox | [agents.md](references/agents.md) |
- | Do deep web research with reports | `cli agents deerflow` | [agents.md](references/agents.md) |
- | Code execution / data analysis agent | `cli agents smolagents --executor docker` | [agents.md](references/agents.md) |
- | Build a RAG system | `RetrieverFactory.create()` with a `vector` or `ensemble` retriever | [rag.md](references/rag.md) |
- | Get strict typed output from an LLM | BAML + `BamlStructuredProcessor` | [baml-structured.md](references/baml-structured.md) |
- | Add a CLI command to your project | Subclass `CliTopCommand`, register in `app_conf.yaml` | [cli-and-init.md](references/cli-and-init.md) |
- | Anonymise PII before sending to LLM | `AnonymizationMiddleware` (Presidio + Faker) | repo: `docs/middleware-pii-and-routing.md` |
- | Run untrusted code | `--sandbox docker` (uses OpenSandbox) | repo: `docs/sandbox_support.md` |
-
- ## Coding conventions (from the project's AGENTS.md)
-
- When generating code that lives inside a genai-tk project, follow the project's house style:
-
- - **Python 3.12+** — use `str | None`, `list[str]` (not `Optional[str]`, `List[str]`)
- - **Imports always absolute** — `from genai_tk.core import LLMFactory`, never relative
- - **Pydantic v2** for all structured data — DTOs, configs, results. Use `model_config = {...}` and `model_post_init()`, never inner `class Config` or `__init__`
- - **`loguru` for logging** — not the stdlib `logging`
- - **Ruff** for formatting + linting, line length 120
- - **Async-first** for I/O — sync wrappers exist for CLI/notebook convenience but the canonical API is async
- - **Docstrings**: Google style, no type info (it's in the signature), no `Raises:` sections
- - **Skills over system prompts**: domain knowledge goes in `skills/<name>/SKILL.md` files loaded on demand by `SkillsMiddleware`, not embedded in agent prompts
- - **YAML-first**: when adding a new agent, retriever, or LLM, add a config entry — don't hard-code in Python
-
- ## Key gotchas
-
- **`model_id@provider` is the canonical identifier.** Anywhere a model is named — CLI flags, YAML, Python — use this format. Bare model names (`gpt-4o-mini`) work via fuzzy lookup but are slower and may resolve unpredictably across versions. Prefer declared aliases in `llm.yaml`.
+ ```python
+ from genai_tk.config_mgmt.config_mngr import global_config, switch_profile
- **Config auto-discovery walks up from the CWD.** If `global_config()` raises `ConfigFileNotFoundError`, the cwd is wrong or `config/app_conf.yaml` doesn't exist yet — run `cli init` to scaffold it.
+ cfg = global_config()
+ cfg.get_str("llm.models.default")
+ cfg.section("my_feature", MyFeatureConfig) # typed Pydantic access; empty model if absent
+ switch_profile("pytest") # sets GENAITK_PROFILE and reloads
+ ```
- **The `:merge` order matters.** Later files override earlier ones. `overrides.yaml` is meant to be the last merged file (and is git-ignored by default), so per-environment tweaks go there.
+ Full semantics in [configuration.md](references/configuration.md).
- **Deep agents need an extra package.** `type: deep` requires `pip install deepagents`. Ad-hoc `LangchainAgent(llm=...)` defaults to `react`.
+ ## Coding Conventions (from upstream AGENTS.md)
- **Deer-flow runs in-process but needs the backend cloned.** Run `cli init --deer-flow` once and set `DEER_FLOW_PATH` in `.env`. The toolkit embeds it; there's no separate server to start.
+ - Python 3.12+: `str | None`, `list[str]`; **avoid `Any`** (use discriminated unions or `TypeAlias`)
+ - Absolute imports only; ruff with line length 120
+ - Pydantic v2 for all structured data: `model_config = {...}`, `model_post_init()`, `model_dump_json()`; no
+ dataclasses, unnamed tuples, or untyped dicts
+ - `loguru` for logging; Google-style docstrings without types or `Raises:`
+ - Read config through typed models: `global_config().section(...)` / `.section_dict(...)`
+ - Tests: use the `fake_llm_id` / `fake_llm` fixtures and fake providers instead of mocks; never hard-code model IDs
+ - Domain knowledge goes in `SKILL.md` files loaded on demand, not in system prompts
- **The OpenSandbox warm-up is worth it.** `cli sandbox start && cli sandbox pull` once per boot cuts container startup from ~28s to ~5s on subsequent agent runs.
+ ## Upstream Doc Drift
- **Skills are loaded on demand, not injected into every prompt.** This is the project's preferred pattern for domain knowledge — write a `SKILL.md`, point an agent profile at the directory, and `SkillsMiddleware` lets the agent read them only when relevant. This is genuinely different from "stuffing the system prompt" and worth using.
+ These upstream docs or bundled skills contradict the code at `7fbd7a3`. Use the right-hand column.
- **`get_llm` accepts deprecated `llm_id`/`llm_tag` kwargs that warn — use `llm=` instead.** The same applies to `get_embeddings(embeddings=...)`.
+ | Docs say | Code does |
+ |----------|-----------|
+ | Config search walks up parent directories | Only `config/app_conf.yaml` under the CWD |
+ | `cli init -t agent-app\|rag-app\|workflow-app\|minimal`, `--with-deer-flow` | Flags are `--name`, `--extra`, `--with-graph`, `--graph-path`, `--force` |
+ | `cli mcp serve\|list\|generate` | The group is `cli mcpserver start\|serve\|list\|generate` |
+ | `cli core decision` | `cli core classifier` |
+ | `get_llm(..., reasoning={...})` | Raises; use `"model (high)@provider"` or `reasoning_effort="high"` |
+ | Workflow DSL with `steps:` / `uses:` / `needs:` | `run:` or `pipeline:` with `id`, `run`, `after`, `with` |
+ | `cli rag add-files <retriever> <dir>`, `--include` | `cli rag add-files <dir> -r <retriever> -p <pathspec>` |
+ | Short retriever/backend aliases (`type: vector`, `backend: Chroma`) | Fully qualified class paths are required |
+ | `langchain_agents:` profile lists | `agents:` dict + `agent_defaults:` |
+ | `baml_invoke(inputs=...)`, `cli baml extract --recursive --include` | `baml_invoke(name, params, ...)`, `-p <pathspec>` (default `**/*.md`) |
+ | Bundled `baml_extract`, `rag_ingest`, `office2pdf` workflows (and `cli baml extract`) just work | Their YAML param names don't match the flow signatures; see [workflows.md](references/workflows.md) |
## Anti-Patterns to Avoid
- - **Hard-coding agents/LLMs in Python instead of YAML** — the toolkit's whole point is profile-driven config; adding an agent means adding a profile, not a Python class
- - **Bare model names instead of `model_id@provider`** — fuzzy lookup is slower and can resolve unpredictably; declare aliases in `llm.yaml` and use the canonical identifier
- - **Stuffing the system prompt with domain knowledge** — write `SKILL.md` files and point profiles at them; `SkillsMiddleware` loads them on demand
- - **`type: deep` without `deepagents` installed** — deep agents need the extra package; ad-hoc agents default to `react`
- - **Running untrusted code without the Docker sandbox** — `--sandbox docker` (OpenSandbox) is the isolation boundary; `local` executes in your process
- - **Putting per-environment overrides in tracked config files** — `overrides.yaml` is merged last and git-ignored; that's where environment tweaks belong
- - **Skipping the OpenSandbox warm-up** — `cli sandbox start && cli sandbox pull` once per boot cuts container startup from ~28s to ~5s
- - **Using deprecated `llm_id`/`llm_tag` kwargs** — they warn; use `llm=` / `embeddings=` instead
+ - **Using pre-2026 import paths** — `genai_tk.core.llm_factory`, `genai_tk.utils.config_mngr`, and
+ `genai_tk.core.retriever_factory` are gone with no shims; import from `genai_tk.core.factories` and
+ `genai_tk.config_mgmt.config_mngr`
+ - **Writing `langchain_agents:` / `profiles:` lists or `spec: web_search` tools** — the old profile schema is
+ rejected; use the `agents:` dict and qualified factory paths for tools
+ - **Putting `skills:` on a profile** — it is silently ignored; use `skill_directories:` (deep agents only)
+ - **Bare model names in YAML** — `gpt-4o-mini` triggers fuzzy lookup; always write `model_id@provider`
+ - **Short aliases for retrievers and vector backends** — they fail to resolve; use
+ `genai_tk.core.retrievers.VectorRetriever`, `genai_tk.core.vector_backends.ChromaBackend`, etc.
+ - **Hard-coding agents or LLMs in Python** — add a YAML entry; `LangchainAgent("slug")` only loads and overrides
+ - **`type: deep` or DeerFlow without the `harnessing` extra** — `deepagents` and `deerflow-harness` live there
+ - **Expecting `--sandbox` on `cli agents run` to isolate a LangChain profile** — it only applies to DeerFlow; set
+ `backend: {type: docker}` (or `LangchainAgent(..., sandbox="docker")`) for LangChain profiles
+ - **Running from a subdirectory** — config discovery is CWD-relative; `ConfigFileNotFoundError` usually means
+ you are not at the project root
+ - **Copying examples from upstream `docs/` without checking the code** — see "Upstream Doc Drift"
## When to Use / Not Use
**Use this skill when:**
- - Building genai-tk projects: YAML-driven agents, retrievers, LLM factories
- - Writing `config/*.yaml` profiles (langchain.yaml, deerflow.yaml, llm.yaml, retrievers.yaml)
- - Wiring RAG (`RetrieverFactory`), MCP servers, sandboxes, or BAML structured extraction
- - Scaffolding with `cli init` or extending the CLI with `CliTopCommand`
+ - Working inside a genai-tk project (a `config/app_conf.yaml` and `genai_tk` imports are present)
+ - Writing or fixing agent profiles, provider/LLM config, retrievers, workflows, or `cli.commands` entries
+ - Scaffolding with `cli init`, extending the CLI, or wiring MCP servers, sandboxes, BAML, or trajectories
+ - Migrating code written for older genai-tk versions (old imports, `langchain_agents:`, SmolAgents)
**Do NOT use this skill when:**
- - The project uses plain LangChain/LangGraph without the genai-tk layer — use the langchain skill
- - You need a quick single agent and don't want the config-first machinery — smolagents or langchain skills fit better
- - The user is asking about a different agent framework entirely
+ - The project uses plain LangChain/LangGraph without genai-tk — use the langchain skill
+ - You need a quick standalone agent without config-first machinery — the smolagents or langchain skills fit better
+ - The question is about DeerFlow or DeepAgents used directly, outside genai-tk's harness