一键导入
optional-features
How to add, update, or remove optional feature extras in genai-tk — covering pyproject.toml, features.py registry, import guards, and tests.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
How to add, update, or remove optional feature extras in genai-tk — covering pyproject.toml, features.py registry, import guards, and tests.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Build or modify LangChain, DeepAgent, DeerFlow profiles, agent tools, middleware, checkpointing, skills wiring, and the shared harness layer in genai-tk.
Work on BAML structured extraction, BAML CLI commands, processors, utilities, and Prefect BAML workflow integration in genai-tk.
Work on browser automation, sandbox browser tools, direct Playwright tools, AioSandbox backend, and sandbox CLI support in genai-tk.
Add or modify genai-tk Typer CLI commands, dynamic command registration, project scaffolding, and generated Copilot/agent support files.
Work on genai-tk OmegaConf configuration, profiles, overrides, env substitution, and config discovery. Use when editing config/*.yaml or genai_tk.config_mgmt.config_mngr.
Work on core LLM, embeddings, vector store, provider, cache, prompt, and retriever factories in genai-tk. Use when editing genai_tk/core or provider configuration.
| name | optional-features |
| description | How to add, update, or remove optional feature extras in genai-tk — covering pyproject.toml, features.py registry, import guards, and tests. |
| tags | ["packaging","optional-deps","uv","imports","testing"] |
| version | 1.0 |
genai-tk ships a lean core and exposes heavyweight components as opt-in extras. This skill explains the full lifecycle: adding a feature, gating its imports, writing guarded tests, and keeping the registry in sync.
| File | Role |
|---|---|
pyproject.toml → [project.optional-dependencies] | User-facing PyPI extras (uv sync --extra <name>) |
pyproject.toml → [dependency-groups] | Developer-only groups (dev, evals) — NOT on PyPI |
genai_tk/config_mgmt/features.py | FEATURES registry + require_feature() + is_available() |
tests/conftest.py | pytest_collection_modifyitems — skips tests when feature absent |
pyproject.toml[project.optional-dependencies]
my-feature = [
"some-package>=1.0",
"another-package>=2.0",
]
# Keep `all` up to date:
all = ["genai-tk[harnessing,browser,nlp,postgres,streamlit,baml,chromadb,my-feature]"]
Rule: [project.optional-dependencies] is for end users (published to PyPI).
[dependency-groups] is for contributors only (local dev tools like ruff, pytest).
features.pyOpen genai_tk/config_mgmt/features.py and add an entry to FEATURES:
"my-feature": FeatureInfo(
description="Short human description shown in error messages",
packages=["some-package", "another-package"], # PyPI names
check_modules=["some_package", "another_package"], # importable module names
install_cmd='uv sync --extra my-feature # or: uv add "genai-tk[my-feature]"',
),
packages = PyPI package names (used in error messages).
check_modules = Python module names you'd pass to importlib.util.find_spec().
uv run python -c "from genai_tk.config_mgmt.features import missing_features; print(missing_features())"
The new feature should appear in the output if not yet installed.
If the entire module only makes sense when a feature is installed, guard at the top:
from genai_tk.config_mgmt.features import require_feature
require_feature("my-feature", context="cli agents my-command")
from some_package import SomeClass # safe: require_feature raises before this line
def create(self, ...):
from genai_tk.config_mgmt.features import require_feature # noqa: PLC0415
require_feature("my-feature", context="MyClass.create")
from some_package import SomeClass # noqa: PLC0415
...
When the feature is missing the user sees:
ImportError: Optional feature 'my-feature' (required by: MyClass.create) is not installed.
Description : Short human description shown in error messages
Packages : some-package, another-package
Install with: uv sync --extra my-feature # or: uv add "genai-tk[my-feature]"
Use the @pytest.mark.requires_feature marker — registered automatically by tests/conftest.py:
import pytest
@pytest.mark.requires_feature("my-feature")
def test_my_feature_does_something():
from some_package import SomeClass
result = SomeClass().run()
assert result is not None
When a test file imports a production module that calls require_feature() at its
own top level (e.g. aio_backend.py), the @pytest.mark.requires_feature marker
is too late — the import fails before any marker can be applied.
Use pytest.skip(allow_module_level=True) instead:
import pytest
from genai_tk.config_mgmt.features import is_available
if not is_available("harnessing"):
pytest.skip(
"Optional feature 'harnessing' not installed — run: uv sync --extra harnessing",
allow_module_level=True,
)
# Only reached when harnessing is installed:
from deepagents.backends.protocol import SandboxBackendProtocol # noqa: E402
from genai_tk.agents.sandbox.aio_backend import AioSandboxBackend # noqa: E402
The test is skipped (not failed) when the feature is absent, with a message:
SKIPPED — Optional feature 'harnessing' not installed — run: uv sync --extra harnessing
FEATURES in features.py.pyproject.toml → [project.optional-dependencies].all extra accordingly.require_feature("old-name" and is_available("old-name" with grep and update.@pytest.mark.requires_feature("old-name").from genai_tk.config_mgmt.features import available_features, missing_features, is_available
print(available_features()) # ['baml', 'browser', 'chromadb', ...]
print(missing_features()) # ['harnessing', 'nlp', ...]
print(is_available("baml")) # True / False
# Install one feature
uv sync --extra browser
# Install multiple features
uv sync --extra harnessing --extra browser
# Install everything
uv sync --extra all
# During project init
cli init --extra harnessing --extra browser
# In a downstream project using genai-tk
uv add "genai-tk[harnessing,browser]"
| Feature | Packages | Notes |
|---|---|---|
harnessing | deepagents, agent-sandbox, opensandbox, deerflow-harness | Heavy — includes Docker sandbox |
browser | playwright | Run uv run playwright install chromium after install |
nlp | spacy, en-core-web-sm, en-core-web-lg | ~500 MB including models |
postgres | langchain-postgres, psycopg, psycopg2-binary | Requires PostgreSQL server |
streamlit | streamlit | Web UI — not needed for CLI-only use |
baml | baml-cli, baml-lib | Run uv run baml-cli init --dest baml_src after install |
chromadb | chromadb, langchain-chroma | Local vector DB |
There is no automated sync script yet. To verify consistency:
# List extras defined in pyproject.toml
python -c "
import tomllib
p = tomllib.loads(open('pyproject.toml').read())
print(list(p['project']['optional-dependencies'].keys()))
"
# List features registered in features.py
uv run python -c "
from genai_tk.config_mgmt.features import FEATURES
print(list(FEATURES.keys()))
"
Both lists should match (minus the all aggregate extra).