selectools 0.19.0__tar.gz → 0.19.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {selectools-0.19.0/src/selectools.egg-info → selectools-0.19.2}/PKG-INFO +105 -11
- {selectools-0.19.0 → selectools-0.19.2}/README.md +103 -10
- {selectools-0.19.0 → selectools-0.19.2}/pyproject.toml +4 -1
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/__init__.py +35 -3
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/agent/_memory_manager.py +2 -1
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/agent/_provider_caller.py +55 -15
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/agent/_tool_executor.py +85 -25
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/agent/core.py +28 -15
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/audit.py +5 -3
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/coherence.py +30 -4
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/entity_memory.py +8 -3
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/__init__.py +26 -2
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/badge.py +8 -2
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/evaluators.py +397 -1
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/history.py +25 -20
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/html.py +4 -1
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/junit.py +4 -1
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/llm_evaluators.py +323 -41
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/regression.py +7 -3
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/report.py +10 -6
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/snapshot.py +13 -7
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/suite.py +23 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/types.py +27 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/guardrails/format.py +6 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/guardrails/length.py +12 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/guardrails/pii.py +5 -2
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/guardrails/toxicity.py +4 -2
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/knowledge.py +43 -12
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/knowledge_graph.py +11 -1
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/knowledge_store_redis.py +14 -3
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/knowledge_store_supabase.py +11 -3
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/memory.py +21 -6
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/orchestration/checkpoint.py +3 -1
- selectools-0.19.2/src/selectools/patterns/__init__.py +44 -0
- selectools-0.19.2/src/selectools/patterns/debate.py +131 -0
- selectools-0.19.2/src/selectools/patterns/plan_and_execute.py +221 -0
- selectools-0.19.2/src/selectools/patterns/reflective.py +133 -0
- selectools-0.19.2/src/selectools/patterns/team_lead.py +303 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/policy.py +58 -5
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/_openai_compat.py +69 -7
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/anthropic_provider.py +2 -2
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/fallback.py +57 -22
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/gemini_provider.py +28 -4
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/stubs.py +1 -1
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/bm25.py +70 -27
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/chunking.py +77 -30
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/hybrid.py +7 -3
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/loaders.py +33 -4
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/stores/chroma.py +12 -4
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/stores/memory.py +62 -44
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/stores/pinecone.py +19 -5
- selectools-0.19.2/src/selectools/rag/stores/sqlite.py +265 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/tools.py +3 -2
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/security.py +13 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/sessions.py +14 -4
- selectools-0.19.2/src/selectools/stability.py +111 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/toolbox/datetime_tools.py +3 -1
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/toolbox/text_tools.py +10 -2
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/tools/base.py +77 -18
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/tools/decorators.py +43 -4
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/tools/loader.py +23 -7
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/tools/registry.py +14 -3
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/trace.py +176 -1
- {selectools-0.19.0 → selectools-0.19.2/src/selectools.egg-info}/PKG-INFO +105 -11
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools.egg-info/SOURCES.txt +12 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools.egg-info/requires.txt +1 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_audit.py +46 -0
- selectools-0.19.2/tests/test_coherence.py +272 -0
- selectools-0.19.2/tests/test_concurrency_smoke.py +617 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_entity_memory.py +70 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_evals_advanced.py +26 -4
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_evals_e2e.py +2 -2
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_evals_final.py +40 -0
- selectools-0.19.2/tests/test_evals_hardening.py +1016 -0
- selectools-0.19.2/tests/test_evals_v0191.py +602 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_guardrails.py +137 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_knowledge_graph.py +127 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_knowledge_store_redis.py +41 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_knowledge_store_supabase.py +46 -0
- selectools-0.19.2/tests/test_knowledge_stores.py +631 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_memory.py +71 -0
- selectools-0.19.2/tests/test_patterns.py +520 -0
- selectools-0.19.2/tests/test_policy.py +403 -0
- selectools-0.19.2/tests/test_property_based.py +298 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_security.py +58 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_sessions_edge_cases.py +28 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_sessions_redis.py +52 -0
- selectools-0.19.2/tests/test_stability.py +195 -0
- selectools-0.19.2/tests/test_trace_html.py +159 -0
- selectools-0.19.0/src/selectools/rag/stores/sqlite.py +0 -247
- selectools-0.19.0/tests/test_coherence.py +0 -146
- selectools-0.19.0/tests/test_evals_hardening.py +0 -527
- selectools-0.19.0/tests/test_knowledge_stores.py +0 -299
- selectools-0.19.0/tests/test_policy.py +0 -215
- {selectools-0.19.0 → selectools-0.19.2}/LICENSE +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/setup.cfg +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/agent/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/agent/_lifecycle.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/agent/config.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/agent/config_groups.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/analytics.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/cache.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/cache_redis.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/cache_semantic.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/cancellation.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/checkpoint_postgres.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/compose.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/embeddings/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/embeddings/anthropic.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/embeddings/cohere.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/embeddings/gemini.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/embeddings/openai.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/embeddings/provider.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/env.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/__main__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/dataset.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/generator.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/pairwise.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/serve.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/evals/templates.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/exceptions.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/guardrails/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/guardrails/base.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/guardrails/pipeline.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/guardrails/topic.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/mcp/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/mcp/_loop.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/mcp/bridge.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/mcp/client.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/mcp/config.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/mcp/multi.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/mcp/server.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/models.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/observe/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/observe/trace_store.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/observer.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/orchestration/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/orchestration/graph.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/orchestration/node.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/orchestration/state.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/orchestration/supervisor.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/parser.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/pipeline.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/pricing.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/prompt.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/base.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/ollama_provider.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/providers/openai_provider.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/reranker.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/stores/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/rag/vector_store.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/serve/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/serve/app.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/serve/cli.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/serve/models.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/serve/playground.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/structured.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/templates/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/templates/code_reviewer.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/templates/customer_support.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/templates/data_analyst.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/templates/rag_chatbot.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/templates/research_assistant.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/token_estimation.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/toolbox/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/toolbox/data_tools.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/toolbox/file_tools.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/toolbox/memory_tools.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/toolbox/web_tools.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/tools/__init__.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/types.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools/usage.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools.egg-info/dependency_links.txt +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools.egg-info/entry_points.txt +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/src/selectools.egg-info/top_level.txt +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_approval_gate.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_architecture.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_async_observers.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_budget.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_bug_hunt_batch1_core.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_bug_hunt_batch1_security.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_bug_hunt_batch1_tools.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_bug_hunt_regression.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_cache.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_cache_redis.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_cancellation.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_consolidation_regression.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_conversation_branching.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_env.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_evals.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_evals_new_evaluators.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_evals_release.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_evals_v017_features.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_features_in_graph.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_hardening.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_knowledge.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_mcp.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_memory_async.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_memory_boundary.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_memory_integration.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_model_switching.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_multi_agent_edge_cases.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_orchestration_checkpoint.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_orchestration_e2e.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_orchestration_evals.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_orchestration_graph.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_orchestration_integration.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_orchestration_primitives.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_orchestration_supervisor.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_parser.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_phase1_design_patterns.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_pipeline.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_prompt.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_prompt_compression.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_reasoning_strategy.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_routing_mode.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_semantic_cache.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_sessions.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_simple_observer.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_simulation_evals.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_structured.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_structured_config.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_structured_tool_results.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_summarize_on_trim.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_terminal_actions.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_token_estimation.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_tool_caching.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_trace.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_v016_regression.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_v019_features.py +0 -0
- {selectools-0.19.0 → selectools-0.19.2}/tests/test_yaml_config.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: selectools
|
|
3
|
-
Version: 0.19.
|
|
3
|
+
Version: 0.19.2
|
|
4
4
|
Summary: Production-ready AI agents with tool calling, structured output, execution traces, and RAG. Provider-agnostic (OpenAI, Anthropic, Gemini, Ollama) with fallback chains, batch processing, tool policies, streaming, caching, and cost tracking.
|
|
5
5
|
Author-email: John Nichev <johnnichev@gmail.com>
|
|
6
6
|
Maintainer-email: NichevLabs <support@nichevlabs.com>
|
|
@@ -40,6 +40,7 @@ Requires-Dist: isort>=5.13.0; extra == "dev"
|
|
|
40
40
|
Requires-Dist: flake8>=7.0.0; extra == "dev"
|
|
41
41
|
Requires-Dist: mypy>=1.8.0; extra == "dev"
|
|
42
42
|
Requires-Dist: bandit>=1.7.0; extra == "dev"
|
|
43
|
+
Requires-Dist: hypothesis>=6.100.0; extra == "dev"
|
|
43
44
|
Requires-Dist: mkdocs-material>=9.5.0; extra == "dev"
|
|
44
45
|
Provides-Extra: rag
|
|
45
46
|
Requires-Dist: chromadb>=0.4.0; extra == "rag"
|
|
@@ -63,7 +64,7 @@ Dynamic: license-file
|
|
|
63
64
|
[](https://johnnichev.github.io/selectools)
|
|
64
65
|
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
65
66
|
[](https://www.python.org/downloads/)
|
|
66
|
-
[](https://johnnichev.github.io/selectools/modules/EVALS/)
|
|
67
68
|
|
|
68
69
|
An open-source project from **[NichevLabs](https://nichevlabs.com)**.
|
|
69
70
|
|
|
@@ -83,7 +84,83 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
|
|
|
83
84
|
# selectools serve agent.yaml
|
|
84
85
|
```
|
|
85
86
|
|
|
86
|
-
## What's New in v0.
|
|
87
|
+
## What's New in v0.19
|
|
88
|
+
|
|
89
|
+
### v0.19.2 — Enterprise Hardening
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from selectools.stability import stable, beta, deprecated
|
|
93
|
+
from selectools import trace_to_html
|
|
94
|
+
|
|
95
|
+
# Mark your own extensions with stability levels
|
|
96
|
+
@stable
|
|
97
|
+
class MyProductionAgent: ...
|
|
98
|
+
|
|
99
|
+
@beta
|
|
100
|
+
class MyExperimentalFeature: ...
|
|
101
|
+
|
|
102
|
+
@deprecated(since="0.19", replacement="MyProductionAgent")
|
|
103
|
+
class MyOldAgent: ...
|
|
104
|
+
|
|
105
|
+
# Visualise any trace as a waterfall HTML timeline
|
|
106
|
+
Path("trace.html").write_text(trace_to_html(result.trace))
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
- **Stability markers** — `@stable`, `@beta`, `@deprecated(since, replacement)` for public API signalling
|
|
110
|
+
- **Trace HTML viewer** — `trace_to_html(trace)` renders a standalone waterfall timeline
|
|
111
|
+
- **Deprecation policy** — 2-minor-version window, programmatic introspection via `.__stability__`
|
|
112
|
+
- **Security audit** — all 41 `# nosec` annotations reviewed and published in `docs/SECURITY.md`
|
|
113
|
+
- **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (3135 tests total)
|
|
114
|
+
|
|
115
|
+
### v0.19.1 — Advanced Agent Patterns
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
from selectools.patterns import PlanAndExecuteAgent, ReflectiveAgent, DebateAgent, TeamLeadAgent
|
|
119
|
+
|
|
120
|
+
# PlanAndExecute — planner generates typed steps, executor runs them sequentially
|
|
121
|
+
agent = PlanAndExecuteAgent(planner=planner, executor=executor, provider=provider)
|
|
122
|
+
result = agent.run("Research and write a blog post about LLM safety")
|
|
123
|
+
|
|
124
|
+
# ReflectiveAgent — actor drafts, critic reviews, actor revises until approved
|
|
125
|
+
agent = ReflectiveAgent(actor=actor, critic=critic, provider=provider, max_reflections=3)
|
|
126
|
+
result = agent.run("Draft a product announcement email")
|
|
127
|
+
|
|
128
|
+
# DebateAgent — multiple agents argue, judge synthesizes conclusion
|
|
129
|
+
agent = DebateAgent(agents={"optimist": opt, "skeptic": skep}, judge=judge, provider=provider)
|
|
130
|
+
result = agent.run("Should we migrate our infrastructure to microservices?")
|
|
131
|
+
|
|
132
|
+
# TeamLeadAgent — lead delegates subtasks, team executes in parallel or sequentially
|
|
133
|
+
agent = TeamLeadAgent(lead=lead, team={"researcher": r, "writer": w}, provider=provider)
|
|
134
|
+
result = agent.run("Produce a competitive analysis report")
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
- **PlanAndExecuteAgent** — Typed `PlanStep` list; optional replanning on step failure
|
|
138
|
+
- **ReflectiveAgent** — Actor–critic loop with `ReflectionRound` records per revision
|
|
139
|
+
- **DebateAgent** — N-agent debate with transcript, judge synthesis, `DebateResult`
|
|
140
|
+
- **TeamLeadAgent** — `sequential`, `parallel`, or `dynamic` delegation strategies
|
|
141
|
+
|
|
142
|
+
### v0.19.0 — Serve, Deploy & Complete Composition
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# One command deploys your agent over HTTP with SSE streaming
|
|
146
|
+
# selectools serve agent.yaml
|
|
147
|
+
|
|
148
|
+
# Compose tools into a single callable
|
|
149
|
+
from selectools import compose
|
|
150
|
+
search_and_summarize = compose(search_web, summarize)
|
|
151
|
+
|
|
152
|
+
# Streaming composition
|
|
153
|
+
async for chunk in pipeline.astream("input"):
|
|
154
|
+
print(chunk)
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
- **`selectools serve`** — HTTP deployment with SSE streaming, Playground UI, `/health`, `/schema`
|
|
158
|
+
- **YAML config** — `AgentConfig.from_yaml("agent.yaml")`, 5 built-in templates
|
|
159
|
+
- **`compose()`** — Chain tools into composite tool; `retry()` and `cache_step()` wrappers
|
|
160
|
+
- **PostgresCheckpointStore** — Durable graph checkpointing backed by PostgreSQL
|
|
161
|
+
|
|
162
|
+
<details>
|
|
163
|
+
<summary><strong>v0.18.x highlights</strong></summary>
|
|
87
164
|
|
|
88
165
|
### v0.18.0 — Multi-Agent Orchestration
|
|
89
166
|
|
|
@@ -154,6 +231,8 @@ route = branch(
|
|
|
154
231
|
- **parallel()** — Fan-out to multiple steps and merge results
|
|
155
232
|
- **branch()** — Conditional routing based on input data
|
|
156
233
|
|
|
234
|
+
</details>
|
|
235
|
+
|
|
157
236
|
<details>
|
|
158
237
|
<summary><strong>v0.17.x highlights</strong></summary>
|
|
159
238
|
|
|
@@ -276,7 +355,7 @@ report = suite.run()
|
|
|
276
355
|
report.to_html("report.html")
|
|
277
356
|
```
|
|
278
357
|
|
|
279
|
-
- **
|
|
358
|
+
- **50 Evaluators** — 30 deterministic + 21 LLM-as-judge
|
|
280
359
|
- **A/B Testing**, regression detection, snapshot testing
|
|
281
360
|
- **HTML reports**, JUnit XML, CLI, GitHub Action integration
|
|
282
361
|
|
|
@@ -316,10 +395,12 @@ report.to_html("report.html")
|
|
|
316
395
|
| `StateGraph` + `add_node` + `add_edge` + `compile()` | `AgentGraph.chain(a, b, c).run(prompt)` |
|
|
317
396
|
| LCEL `prompt \| llm \| parser` with Runnable protocol | `@step` + `\|` on plain functions |
|
|
318
397
|
| `interrupt()` restarts the whole node on resume | `yield InterruptRequest()` resumes at yield point |
|
|
319
|
-
| LangSmith (paid) for tracing and evals | Built-in:
|
|
398
|
+
| LangSmith (paid) for tracing and evals | Built-in: 50 evaluators + traces, zero cost |
|
|
320
399
|
| 5+ packages (`langchain-core`, `langgraph`, `langsmith`...) | 1 package: `pip install selectools` |
|
|
321
400
|
| `langserve` for deployment | `selectools serve agent.yaml` |
|
|
322
401
|
|
|
402
|
+
> Full migration guide with code examples: **[Coming from LangChain](docs/MIGRATION.md)**
|
|
403
|
+
|
|
323
404
|
## Why Selectools
|
|
324
405
|
|
|
325
406
|
| Capability | What You Get |
|
|
@@ -346,7 +427,7 @@ report.to_html("report.html")
|
|
|
346
427
|
| **Knowledge Graph** | Relationship triple extraction with in-memory and SQLite storage and keyword-based querying. |
|
|
347
428
|
| **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` tool. |
|
|
348
429
|
| **MCP Integration** | Connect to any MCP tool server (stdio + HTTP). MCPClient, MultiMCPClient, MCPServer. Circuit breaker, retry, graceful degradation. |
|
|
349
|
-
| **Eval Framework** |
|
|
430
|
+
| **Eval Framework** | 50 built-in evaluators (30 deterministic + 21 LLM-as-judge). A/B testing, regression detection, snapshot testing, HTML reports, JUnit XML, CI integration. |
|
|
350
431
|
| **Multi-Agent Orchestration** | `AgentGraph` for directed agent graphs, `SupervisorAgent` with 4 strategies, HITL via generator nodes, parallel execution, checkpointing, subgraph composition. |
|
|
351
432
|
| **Composable Pipelines** | `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms with plain Python. |
|
|
352
433
|
| **AgentObserver Protocol** | 45-event lifecycle observer with `run_id`/`call_id` correlation. Built-in `LoggingObserver` + `SimpleStepObserver`. |
|
|
@@ -382,10 +463,10 @@ report.to_html("report.html")
|
|
|
382
463
|
- **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
|
|
383
464
|
- **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
|
|
384
465
|
- **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
|
|
385
|
-
- **
|
|
386
|
-
- **Built-in Eval Framework**:
|
|
466
|
+
- **75 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, and more
|
|
467
|
+
- **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
|
|
387
468
|
- **AgentObserver Protocol**: 45 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
|
|
388
|
-
- **
|
|
469
|
+
- **3135 Tests**: Unit, integration, regression, and E2E with real API calls
|
|
389
470
|
|
|
390
471
|
## Install
|
|
391
472
|
|
|
@@ -934,6 +1015,18 @@ Examples are numbered by difficulty. Start from 01 and work your way up.
|
|
|
934
1015
|
| 59 | `59_agent_graph_checkpointing.py` | Checkpoint, interrupt, resume | No |
|
|
935
1016
|
| 60 | `60_supervisor_agent.py` | SupervisorAgent with 4 strategies | No |
|
|
936
1017
|
| 61 | `61_agent_graph_subgraph.py` | Nested subgraph composition | No |
|
|
1018
|
+
| 62 | `62_yaml_config.py` | Load AgentConfig from YAML | No |
|
|
1019
|
+
| 63 | `63_agent_templates.py` | Built-in agent templates | No |
|
|
1020
|
+
| 64 | `64_selectools_serve.py` | Serve agent over HTTP with `selectools serve` | No |
|
|
1021
|
+
| 65 | `65_tool_composition.py` | `compose()` tool chaining | No |
|
|
1022
|
+
| 66 | `66_streaming_pipeline.py` | `pipeline.astream()` streaming composition | No |
|
|
1023
|
+
| 67 | `67_type_safe_pipeline.py` | Type-safe step contracts | No |
|
|
1024
|
+
| 68 | `68_postgres_checkpoints.py` | PostgresCheckpointStore for AgentGraph | Yes + `[postgres]` |
|
|
1025
|
+
| 69 | `69_trace_store.py` | Trace storage and querying | No |
|
|
1026
|
+
| 70 | `70_plan_and_execute.py` | PlanAndExecuteAgent with typed steps | No |
|
|
1027
|
+
| 71 | `71_reflective_agent.py` | ReflectiveAgent actor–critic loop | No |
|
|
1028
|
+
| 72 | `72_debate_agent.py` | DebateAgent with optimist/skeptic/judge | No |
|
|
1029
|
+
| 73 | `73_team_lead_agent.py` | TeamLeadAgent with all 3 delegation strategies | No |
|
|
937
1030
|
|
|
938
1031
|
Run any example:
|
|
939
1032
|
|
|
@@ -970,12 +1063,13 @@ Also available in [`docs/`](docs/README.md):
|
|
|
970
1063
|
| [GUARDRAILS](docs/modules/GUARDRAILS.md) | Input/output validation pipeline |
|
|
971
1064
|
| [AUDIT](docs/modules/AUDIT.md) | JSONL audit logging |
|
|
972
1065
|
| [SECURITY](docs/modules/SECURITY.md) | Screening & coherence checking |
|
|
973
|
-
| [EVALS](docs/modules/EVALS.md) |
|
|
1066
|
+
| [EVALS](docs/modules/EVALS.md) | 50 evaluators, A/B testing, regression |
|
|
974
1067
|
| [MCP](docs/modules/MCP.md) | MCP client/server integration |
|
|
975
1068
|
| [BUDGET](docs/modules/BUDGET.md) | Token/cost budget limits |
|
|
976
1069
|
| [CANCELLATION](docs/modules/CANCELLATION.md) | Cooperative cancellation |
|
|
977
1070
|
| [ORCHESTRATION](docs/modules/ORCHESTRATION.md) | AgentGraph, routing, parallel, HITL |
|
|
978
1071
|
| [SUPERVISOR](docs/modules/SUPERVISOR.md) | SupervisorAgent, 4 strategies |
|
|
1072
|
+
| [PATTERNS](docs/modules/PATTERNS.md) | PlanAndExecute, Reflective, Debate, TeamLead |
|
|
979
1073
|
| [PARSER](docs/modules/PARSER.md) | Tool call parsing |
|
|
980
1074
|
| [PROMPT](docs/modules/PROMPT.md) | System prompt generation |
|
|
981
1075
|
|
|
@@ -986,7 +1080,7 @@ pytest tests/ -x -q # All tests
|
|
|
986
1080
|
pytest tests/ -k "not e2e" # Skip E2E (no API keys needed)
|
|
987
1081
|
```
|
|
988
1082
|
|
|
989
|
-
|
|
1083
|
+
3135 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, and E2E integration with real API calls.
|
|
990
1084
|
|
|
991
1085
|
## License
|
|
992
1086
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
[](https://johnnichev.github.io/selectools)
|
|
5
5
|
[](https://www.apache.org/licenses/LICENSE-2.0)
|
|
6
6
|
[](https://www.python.org/downloads/)
|
|
7
|
-
[](https://johnnichev.github.io/selectools/modules/EVALS/)
|
|
8
8
|
|
|
9
9
|
An open-source project from **[NichevLabs](https://nichevlabs.com)**.
|
|
10
10
|
|
|
@@ -24,7 +24,83 @@ result = AgentGraph.chain(planner, writer, reviewer).run("Write a blog post")
|
|
|
24
24
|
# selectools serve agent.yaml
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
## What's New in v0.
|
|
27
|
+
## What's New in v0.19
|
|
28
|
+
|
|
29
|
+
### v0.19.2 — Enterprise Hardening
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from selectools.stability import stable, beta, deprecated
|
|
33
|
+
from selectools import trace_to_html
|
|
34
|
+
|
|
35
|
+
# Mark your own extensions with stability levels
|
|
36
|
+
@stable
|
|
37
|
+
class MyProductionAgent: ...
|
|
38
|
+
|
|
39
|
+
@beta
|
|
40
|
+
class MyExperimentalFeature: ...
|
|
41
|
+
|
|
42
|
+
@deprecated(since="0.19", replacement="MyProductionAgent")
|
|
43
|
+
class MyOldAgent: ...
|
|
44
|
+
|
|
45
|
+
# Visualise any trace as a waterfall HTML timeline
|
|
46
|
+
Path("trace.html").write_text(trace_to_html(result.trace))
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
- **Stability markers** — `@stable`, `@beta`, `@deprecated(since, replacement)` for public API signalling
|
|
50
|
+
- **Trace HTML viewer** — `trace_to_html(trace)` renders a standalone waterfall timeline
|
|
51
|
+
- **Deprecation policy** — 2-minor-version window, programmatic introspection via `.__stability__`
|
|
52
|
+
- **Security audit** — all 41 `# nosec` annotations reviewed and published in `docs/SECURITY.md`
|
|
53
|
+
- **Quality infrastructure** — property-based tests (Hypothesis), thread-safety smoke suite, 5 new production simulations (3135 tests total)
|
|
54
|
+
|
|
55
|
+
### v0.19.1 — Advanced Agent Patterns
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from selectools.patterns import PlanAndExecuteAgent, ReflectiveAgent, DebateAgent, TeamLeadAgent
|
|
59
|
+
|
|
60
|
+
# PlanAndExecute — planner generates typed steps, executor runs them sequentially
|
|
61
|
+
agent = PlanAndExecuteAgent(planner=planner, executor=executor, provider=provider)
|
|
62
|
+
result = agent.run("Research and write a blog post about LLM safety")
|
|
63
|
+
|
|
64
|
+
# ReflectiveAgent — actor drafts, critic reviews, actor revises until approved
|
|
65
|
+
agent = ReflectiveAgent(actor=actor, critic=critic, provider=provider, max_reflections=3)
|
|
66
|
+
result = agent.run("Draft a product announcement email")
|
|
67
|
+
|
|
68
|
+
# DebateAgent — multiple agents argue, judge synthesizes conclusion
|
|
69
|
+
agent = DebateAgent(agents={"optimist": opt, "skeptic": skep}, judge=judge, provider=provider)
|
|
70
|
+
result = agent.run("Should we migrate our infrastructure to microservices?")
|
|
71
|
+
|
|
72
|
+
# TeamLeadAgent — lead delegates subtasks, team executes in parallel or sequentially
|
|
73
|
+
agent = TeamLeadAgent(lead=lead, team={"researcher": r, "writer": w}, provider=provider)
|
|
74
|
+
result = agent.run("Produce a competitive analysis report")
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
- **PlanAndExecuteAgent** — Typed `PlanStep` list; optional replanning on step failure
|
|
78
|
+
- **ReflectiveAgent** — Actor–critic loop with `ReflectionRound` records per revision
|
|
79
|
+
- **DebateAgent** — N-agent debate with transcript, judge synthesis, `DebateResult`
|
|
80
|
+
- **TeamLeadAgent** — `sequential`, `parallel`, or `dynamic` delegation strategies
|
|
81
|
+
|
|
82
|
+
### v0.19.0 — Serve, Deploy & Complete Composition
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
# One command deploys your agent over HTTP with SSE streaming
|
|
86
|
+
# selectools serve agent.yaml
|
|
87
|
+
|
|
88
|
+
# Compose tools into a single callable
|
|
89
|
+
from selectools import compose
|
|
90
|
+
search_and_summarize = compose(search_web, summarize)
|
|
91
|
+
|
|
92
|
+
# Streaming composition
|
|
93
|
+
async for chunk in pipeline.astream("input"):
|
|
94
|
+
print(chunk)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
- **`selectools serve`** — HTTP deployment with SSE streaming, Playground UI, `/health`, `/schema`
|
|
98
|
+
- **YAML config** — `AgentConfig.from_yaml("agent.yaml")`, 5 built-in templates
|
|
99
|
+
- **`compose()`** — Chain tools into composite tool; `retry()` and `cache_step()` wrappers
|
|
100
|
+
- **PostgresCheckpointStore** — Durable graph checkpointing backed by PostgreSQL
|
|
101
|
+
|
|
102
|
+
<details>
|
|
103
|
+
<summary><strong>v0.18.x highlights</strong></summary>
|
|
28
104
|
|
|
29
105
|
### v0.18.0 — Multi-Agent Orchestration
|
|
30
106
|
|
|
@@ -95,6 +171,8 @@ route = branch(
|
|
|
95
171
|
- **parallel()** — Fan-out to multiple steps and merge results
|
|
96
172
|
- **branch()** — Conditional routing based on input data
|
|
97
173
|
|
|
174
|
+
</details>
|
|
175
|
+
|
|
98
176
|
<details>
|
|
99
177
|
<summary><strong>v0.17.x highlights</strong></summary>
|
|
100
178
|
|
|
@@ -217,7 +295,7 @@ report = suite.run()
|
|
|
217
295
|
report.to_html("report.html")
|
|
218
296
|
```
|
|
219
297
|
|
|
220
|
-
- **
|
|
298
|
+
- **50 Evaluators** — 30 deterministic + 21 LLM-as-judge
|
|
221
299
|
- **A/B Testing**, regression detection, snapshot testing
|
|
222
300
|
- **HTML reports**, JUnit XML, CLI, GitHub Action integration
|
|
223
301
|
|
|
@@ -257,10 +335,12 @@ report.to_html("report.html")
|
|
|
257
335
|
| `StateGraph` + `add_node` + `add_edge` + `compile()` | `AgentGraph.chain(a, b, c).run(prompt)` |
|
|
258
336
|
| LCEL `prompt \| llm \| parser` with Runnable protocol | `@step` + `\|` on plain functions |
|
|
259
337
|
| `interrupt()` restarts the whole node on resume | `yield InterruptRequest()` resumes at yield point |
|
|
260
|
-
| LangSmith (paid) for tracing and evals | Built-in:
|
|
338
|
+
| LangSmith (paid) for tracing and evals | Built-in: 50 evaluators + traces, zero cost |
|
|
261
339
|
| 5+ packages (`langchain-core`, `langgraph`, `langsmith`...) | 1 package: `pip install selectools` |
|
|
262
340
|
| `langserve` for deployment | `selectools serve agent.yaml` |
|
|
263
341
|
|
|
342
|
+
> Full migration guide with code examples: **[Coming from LangChain](docs/MIGRATION.md)**
|
|
343
|
+
|
|
264
344
|
## Why Selectools
|
|
265
345
|
|
|
266
346
|
| Capability | What You Get |
|
|
@@ -287,7 +367,7 @@ report.to_html("report.html")
|
|
|
287
367
|
| **Knowledge Graph** | Relationship triple extraction with in-memory and SQLite storage and keyword-based querying. |
|
|
288
368
|
| **Cross-Session Knowledge** | Daily logs + persistent facts with auto-registered `remember` tool. |
|
|
289
369
|
| **MCP Integration** | Connect to any MCP tool server (stdio + HTTP). MCPClient, MultiMCPClient, MCPServer. Circuit breaker, retry, graceful degradation. |
|
|
290
|
-
| **Eval Framework** |
|
|
370
|
+
| **Eval Framework** | 50 built-in evaluators (30 deterministic + 21 LLM-as-judge). A/B testing, regression detection, snapshot testing, HTML reports, JUnit XML, CI integration. |
|
|
291
371
|
| **Multi-Agent Orchestration** | `AgentGraph` for directed agent graphs, `SupervisorAgent` with 4 strategies, HITL via generator nodes, parallel execution, checkpointing, subgraph composition. |
|
|
292
372
|
| **Composable Pipelines** | `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms with plain Python. |
|
|
293
373
|
| **AgentObserver Protocol** | 45-event lifecycle observer with `run_id`/`call_id` correlation. Built-in `LoggingObserver` + `SimpleStepObserver`. |
|
|
@@ -323,10 +403,10 @@ report.to_html("report.html")
|
|
|
323
403
|
- **Conversation Branching**: `ConversationMemory.branch()` and `SessionStore.branch()` for A/B exploration and checkpointing
|
|
324
404
|
- **Multi-Agent Orchestration**: `AgentGraph` with routing, parallel execution, HITL, checkpointing; `SupervisorAgent` with 4 strategies (plan_and_execute, round_robin, dynamic, magentic)
|
|
325
405
|
- **Composable Pipelines**: `Pipeline` + `@step` + `|` operator + `parallel()` + `branch()` — chain agents, tools, and transforms
|
|
326
|
-
- **
|
|
327
|
-
- **Built-in Eval Framework**:
|
|
406
|
+
- **75 Examples**: Multi-agent graphs, RAG, hybrid search, streaming, structured output, traces, batch, policy, observer, guardrails, audit, sessions, entity memory, knowledge graph, eval framework, advanced agent patterns, stability markers, HTML trace viewer, and more
|
|
407
|
+
- **Built-in Eval Framework**: 50 evaluators (30 deterministic + 21 LLM-as-judge), A/B testing, regression detection, HTML reports, JUnit XML, snapshot testing
|
|
328
408
|
- **AgentObserver Protocol**: 45 lifecycle events with `run_id` correlation, `LoggingObserver`, `SimpleStepObserver`, OTel export
|
|
329
|
-
- **
|
|
409
|
+
- **3135 Tests**: Unit, integration, regression, and E2E with real API calls
|
|
330
410
|
|
|
331
411
|
## Install
|
|
332
412
|
|
|
@@ -875,6 +955,18 @@ Examples are numbered by difficulty. Start from 01 and work your way up.
|
|
|
875
955
|
| 59 | `59_agent_graph_checkpointing.py` | Checkpoint, interrupt, resume | No |
|
|
876
956
|
| 60 | `60_supervisor_agent.py` | SupervisorAgent with 4 strategies | No |
|
|
877
957
|
| 61 | `61_agent_graph_subgraph.py` | Nested subgraph composition | No |
|
|
958
|
+
| 62 | `62_yaml_config.py` | Load AgentConfig from YAML | No |
|
|
959
|
+
| 63 | `63_agent_templates.py` | Built-in agent templates | No |
|
|
960
|
+
| 64 | `64_selectools_serve.py` | Serve agent over HTTP with `selectools serve` | No |
|
|
961
|
+
| 65 | `65_tool_composition.py` | `compose()` tool chaining | No |
|
|
962
|
+
| 66 | `66_streaming_pipeline.py` | `pipeline.astream()` streaming composition | No |
|
|
963
|
+
| 67 | `67_type_safe_pipeline.py` | Type-safe step contracts | No |
|
|
964
|
+
| 68 | `68_postgres_checkpoints.py` | PostgresCheckpointStore for AgentGraph | Yes + `[postgres]` |
|
|
965
|
+
| 69 | `69_trace_store.py` | Trace storage and querying | No |
|
|
966
|
+
| 70 | `70_plan_and_execute.py` | PlanAndExecuteAgent with typed steps | No |
|
|
967
|
+
| 71 | `71_reflective_agent.py` | ReflectiveAgent actor–critic loop | No |
|
|
968
|
+
| 72 | `72_debate_agent.py` | DebateAgent with optimist/skeptic/judge | No |
|
|
969
|
+
| 73 | `73_team_lead_agent.py` | TeamLeadAgent with all 3 delegation strategies | No |
|
|
878
970
|
|
|
879
971
|
Run any example:
|
|
880
972
|
|
|
@@ -911,12 +1003,13 @@ Also available in [`docs/`](docs/README.md):
|
|
|
911
1003
|
| [GUARDRAILS](docs/modules/GUARDRAILS.md) | Input/output validation pipeline |
|
|
912
1004
|
| [AUDIT](docs/modules/AUDIT.md) | JSONL audit logging |
|
|
913
1005
|
| [SECURITY](docs/modules/SECURITY.md) | Screening & coherence checking |
|
|
914
|
-
| [EVALS](docs/modules/EVALS.md) |
|
|
1006
|
+
| [EVALS](docs/modules/EVALS.md) | 50 evaluators, A/B testing, regression |
|
|
915
1007
|
| [MCP](docs/modules/MCP.md) | MCP client/server integration |
|
|
916
1008
|
| [BUDGET](docs/modules/BUDGET.md) | Token/cost budget limits |
|
|
917
1009
|
| [CANCELLATION](docs/modules/CANCELLATION.md) | Cooperative cancellation |
|
|
918
1010
|
| [ORCHESTRATION](docs/modules/ORCHESTRATION.md) | AgentGraph, routing, parallel, HITL |
|
|
919
1011
|
| [SUPERVISOR](docs/modules/SUPERVISOR.md) | SupervisorAgent, 4 strategies |
|
|
1012
|
+
| [PATTERNS](docs/modules/PATTERNS.md) | PlanAndExecute, Reflective, Debate, TeamLead |
|
|
920
1013
|
| [PARSER](docs/modules/PARSER.md) | Tool call parsing |
|
|
921
1014
|
| [PROMPT](docs/modules/PROMPT.md) | System prompt generation |
|
|
922
1015
|
|
|
@@ -927,7 +1020,7 @@ pytest tests/ -x -q # All tests
|
|
|
927
1020
|
pytest tests/ -k "not e2e" # Skip E2E (no API keys needed)
|
|
928
1021
|
```
|
|
929
1022
|
|
|
930
|
-
|
|
1023
|
+
3135 tests covering parsing, agent loop, providers, RAG pipeline, hybrid search, advanced chunking, dynamic tools, caching, streaming, guardrails, sessions, memory, eval framework, budget/cancellation, knowledge stores, orchestration, pipelines, agent patterns, stability markers, trace viewer, and E2E integration with real API calls.
|
|
931
1024
|
|
|
932
1025
|
## License
|
|
933
1026
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "selectools"
|
|
7
|
-
version = "0.19.
|
|
7
|
+
version = "0.19.2"
|
|
8
8
|
description = "Production-ready AI agents with tool calling, structured output, execution traces, and RAG. Provider-agnostic (OpenAI, Anthropic, Gemini, Ollama) with fallback chains, batch processing, tool policies, streaming, caching, and cost tracking."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
@@ -51,6 +51,7 @@ dev = [
|
|
|
51
51
|
"flake8>=7.0.0",
|
|
52
52
|
"mypy>=1.8.0",
|
|
53
53
|
"bandit>=1.7.0",
|
|
54
|
+
"hypothesis>=6.100.0",
|
|
54
55
|
"mkdocs-material>=9.5.0",
|
|
55
56
|
]
|
|
56
57
|
rag = [
|
|
@@ -142,8 +143,10 @@ testpaths = ["tests"]
|
|
|
142
143
|
pythonpath = ["src", "."]
|
|
143
144
|
asyncio_mode = "strict"
|
|
144
145
|
addopts = "-v"
|
|
146
|
+
python_files = ["test_*.py", "sim_*.py"]
|
|
145
147
|
markers = [
|
|
146
148
|
"e2e: mark test as end-to-end (requires real API keys, use --run-e2e to run)",
|
|
149
|
+
"integration: mark test as integration (no API keys, uses real implementations with mocks)",
|
|
147
150
|
"openai: mark test as requiring OpenAI API key",
|
|
148
151
|
"anthropic: mark test as requiring Anthropic API key",
|
|
149
152
|
"gemini: mark test as requiring Gemini API key",
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"""Public exports for the selectools package."""
|
|
2
2
|
|
|
3
|
-
__version__ = "0.19.
|
|
3
|
+
__version__ = "0.19.2"
|
|
4
4
|
|
|
5
5
|
# Import submodules (lazy loading for optional dependencies)
|
|
6
|
-
from . import embeddings, evals, guardrails, models, rag, toolbox
|
|
6
|
+
from . import embeddings, evals, guardrails, models, patterns, rag, toolbox
|
|
7
7
|
from .agent import Agent, AgentConfig
|
|
8
8
|
from .agent.config_groups import (
|
|
9
9
|
BudgetConfig,
|
|
@@ -99,6 +99,19 @@ from .orchestration import (
|
|
|
99
99
|
SupervisorStrategy,
|
|
100
100
|
)
|
|
101
101
|
from .parser import ToolCallParser
|
|
102
|
+
from .patterns import (
|
|
103
|
+
DebateAgent,
|
|
104
|
+
DebateResult,
|
|
105
|
+
DebateRound,
|
|
106
|
+
PlanAndExecuteAgent,
|
|
107
|
+
PlanStep,
|
|
108
|
+
ReflectionRound,
|
|
109
|
+
ReflectiveAgent,
|
|
110
|
+
ReflectiveResult,
|
|
111
|
+
Subtask,
|
|
112
|
+
TeamLeadAgent,
|
|
113
|
+
TeamLeadResult,
|
|
114
|
+
)
|
|
102
115
|
from .pipeline import Pipeline, Step, StepResult, branch, cache_step, parallel, retry, step
|
|
103
116
|
from .policy import PolicyDecision, PolicyResult, ToolPolicy
|
|
104
117
|
from .pricing import PRICING, calculate_cost, calculate_embedding_cost, get_model_pricing
|
|
@@ -116,10 +129,11 @@ from .sessions import (
|
|
|
116
129
|
SessionStore,
|
|
117
130
|
SQLiteSessionStore,
|
|
118
131
|
)
|
|
132
|
+
from .stability import beta, deprecated, stable
|
|
119
133
|
from .structured import ResponseFormat
|
|
120
134
|
from .token_estimation import TokenEstimate, estimate_run_tokens, estimate_tokens
|
|
121
135
|
from .tools import Tool, ToolParameter, ToolRegistry, tool
|
|
122
|
-
from .trace import AgentTrace, StepType, TraceStep
|
|
136
|
+
from .trace import AgentTrace, StepType, TraceStep, trace_to_html
|
|
123
137
|
from .types import AgentResult, Message, Role, ToolCall
|
|
124
138
|
from .usage import AgentUsage, UsageStats
|
|
125
139
|
|
|
@@ -188,6 +202,10 @@ __all__ = [
|
|
|
188
202
|
"PolicyResult",
|
|
189
203
|
# Structured output
|
|
190
204
|
"ResponseFormat",
|
|
205
|
+
# Stability markers
|
|
206
|
+
"stable",
|
|
207
|
+
"beta",
|
|
208
|
+
"deprecated",
|
|
191
209
|
# Observability
|
|
192
210
|
"AgentObserver",
|
|
193
211
|
"AsyncAgentObserver",
|
|
@@ -196,6 +214,7 @@ __all__ = [
|
|
|
196
214
|
"AgentTrace",
|
|
197
215
|
"StepType",
|
|
198
216
|
"TraceStep",
|
|
217
|
+
"trace_to_html",
|
|
199
218
|
# Guardrails
|
|
200
219
|
"guardrails",
|
|
201
220
|
"Guardrail",
|
|
@@ -267,4 +286,17 @@ __all__ = [
|
|
|
267
286
|
"SupervisorAgent",
|
|
268
287
|
"SupervisorStrategy",
|
|
269
288
|
"ModelSplit",
|
|
289
|
+
# Patterns
|
|
290
|
+
"patterns",
|
|
291
|
+
"PlanAndExecuteAgent",
|
|
292
|
+
"PlanStep",
|
|
293
|
+
"ReflectiveAgent",
|
|
294
|
+
"ReflectionRound",
|
|
295
|
+
"ReflectiveResult",
|
|
296
|
+
"DebateAgent",
|
|
297
|
+
"DebateRound",
|
|
298
|
+
"DebateResult",
|
|
299
|
+
"TeamLeadAgent",
|
|
300
|
+
"Subtask",
|
|
301
|
+
"TeamLeadResult",
|
|
270
302
|
]
|
|
@@ -159,7 +159,8 @@ class _MemoryManagerMixin:
|
|
|
159
159
|
return
|
|
160
160
|
|
|
161
161
|
# Each "turn" is one user + one assistant message, so keep_recent * 2 messages.
|
|
162
|
-
|
|
162
|
+
# Always keep at least 1 message so the current user prompt is never compressed away.
|
|
163
|
+
keep_recent = max(self.config.compress_keep_recent * 2, 1)
|
|
163
164
|
system_msgs: List[Message] = []
|
|
164
165
|
non_system: List[Message] = []
|
|
165
166
|
for m in self._history:
|
|
@@ -3,10 +3,30 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import asyncio
|
|
6
|
+
import threading
|
|
6
7
|
import time
|
|
7
8
|
from concurrent.futures import ThreadPoolExecutor
|
|
8
9
|
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, cast
|
|
9
10
|
|
|
11
|
+
# Module-level singleton for running sync provider calls in an async context.
|
|
12
|
+
# Creating a new ThreadPoolExecutor per call (inside a retry loop) wastes
|
|
13
|
+
# resources and prevents thread reuse (pitfall #20).
|
|
14
|
+
_async_provider_executor: Optional[ThreadPoolExecutor] = None
|
|
15
|
+
_async_provider_executor_lock = threading.Lock()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _get_async_provider_executor() -> ThreadPoolExecutor:
|
|
19
|
+
"""Return the shared ThreadPoolExecutor for sync provider calls in async context."""
|
|
20
|
+
global _async_provider_executor
|
|
21
|
+
if _async_provider_executor is None:
|
|
22
|
+
with _async_provider_executor_lock:
|
|
23
|
+
if _async_provider_executor is None:
|
|
24
|
+
_async_provider_executor = ThreadPoolExecutor(
|
|
25
|
+
max_workers=16, thread_name_prefix="selectools_provider"
|
|
26
|
+
)
|
|
27
|
+
return _async_provider_executor
|
|
28
|
+
|
|
29
|
+
|
|
10
30
|
from ..cache import CacheKeyBuilder
|
|
11
31
|
from ..providers.base import ProviderError
|
|
12
32
|
from ..trace import StepType, TraceStep
|
|
@@ -252,19 +272,39 @@ class _ProviderCallerMixin:
|
|
|
252
272
|
self._effective_model,
|
|
253
273
|
self._system_prompt,
|
|
254
274
|
)
|
|
275
|
+
await self._anotify_observers(
|
|
276
|
+
"on_llm_start",
|
|
277
|
+
run_id,
|
|
278
|
+
self._history,
|
|
279
|
+
self._effective_model,
|
|
280
|
+
self._system_prompt,
|
|
281
|
+
)
|
|
255
282
|
self._notify_observers(
|
|
256
283
|
"on_llm_end",
|
|
257
284
|
run_id,
|
|
258
285
|
cached_msg.content,
|
|
259
286
|
cached_usage,
|
|
260
287
|
)
|
|
288
|
+
await self._anotify_observers(
|
|
289
|
+
"on_llm_end",
|
|
290
|
+
run_id,
|
|
291
|
+
cached_msg.content,
|
|
292
|
+
cached_usage,
|
|
293
|
+
)
|
|
261
294
|
self._notify_observers(
|
|
262
295
|
"on_cache_hit",
|
|
263
296
|
run_id,
|
|
264
297
|
self._effective_model,
|
|
265
298
|
cached_msg.content or "",
|
|
266
299
|
)
|
|
300
|
+
await self._anotify_observers(
|
|
301
|
+
"on_cache_hit",
|
|
302
|
+
run_id,
|
|
303
|
+
self._effective_model,
|
|
304
|
+
cached_msg.content or "",
|
|
305
|
+
)
|
|
267
306
|
self._notify_observers("on_usage", run_id, cached_usage)
|
|
307
|
+
await self._anotify_observers("on_usage", run_id, cached_usage)
|
|
268
308
|
if self.config.verbose:
|
|
269
309
|
print("[agent] cache hit -- skipping provider call")
|
|
270
310
|
if trace is not None:
|
|
@@ -322,21 +362,21 @@ class _ProviderCallerMixin:
|
|
|
322
362
|
)
|
|
323
363
|
response_text = response_msg.content or ""
|
|
324
364
|
else:
|
|
325
|
-
# Fallback to sync in executor
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
365
|
+
# Fallback to sync in executor — reuse the module-level singleton
|
|
366
|
+
# to avoid spawning a new thread pool on every retry attempt.
|
|
367
|
+
loop = asyncio.get_running_loop()
|
|
368
|
+
response_msg, usage_stats = await loop.run_in_executor(
|
|
369
|
+
_get_async_provider_executor(),
|
|
370
|
+
lambda: self.provider.complete(
|
|
371
|
+
model=self._effective_model,
|
|
372
|
+
system_prompt=self._system_prompt,
|
|
373
|
+
messages=self._history,
|
|
374
|
+
tools=self.tools,
|
|
375
|
+
temperature=self.config.temperature,
|
|
376
|
+
max_tokens=self.config.max_tokens,
|
|
377
|
+
timeout=self.config.request_timeout,
|
|
378
|
+
),
|
|
379
|
+
)
|
|
340
380
|
response_text = response_msg.content or ""
|
|
341
381
|
|
|
342
382
|
self.usage.add_usage(usage_stats, tool_name=None)
|