webagents 0.2.2__tar.gz → 0.2.3__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.
- {webagents-0.2.2 → webagents-0.2.3}/.gitignore +2 -1
- {webagents-0.2.2 → webagents-0.2.3}/PKG-INFO +8 -25
- {webagents-0.2.2 → webagents-0.2.3}/README.md +2 -7
- {webagents-0.2.2 → webagents-0.2.3}/docs/agent/endpoints.md +2 -3
- webagents-0.2.3/docs/agent/handoffs.md +409 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/agent/hooks.md +56 -1
- {webagents-0.2.2 → webagents-0.2.3}/docs/agent/overview.md +15 -10
- {webagents-0.2.2 → webagents-0.2.3}/docs/agent/prompts.md +1 -2
- {webagents-0.2.2 → webagents-0.2.3}/docs/agent/skills.md +109 -11
- {webagents-0.2.2 → webagents-0.2.3}/docs/agent/tools.md +10 -11
- webagents-0.2.3/docs/agent/widgets.md +494 -0
- webagents-0.2.3/docs/assets/openai_widgets.png +0 -0
- webagents-0.2.3/docs/assets/widgets.png +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/index.md +42 -2
- {webagents-0.2.2 → webagents-0.2.3}/docs/server.md +2 -2
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/custom.md +2 -4
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/crewai.md +4 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/database.md +4 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/filesystem.md +4 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/google.md +4 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/index.md +13 -1
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/mongodb.md +4 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/n8n.md +4 -0
- webagents-0.2.3/docs/skills/ecosystem/openai.md +481 -0
- webagents-0.2.3/docs/skills/ecosystem/replicate.md +129 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/x_com.md +4 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/zapier.md +4 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/files.md +1 -2
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/kv.md +1 -2
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/notifications.md +1 -2
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/payments.md +1 -1
- {webagents-0.2.2 → webagents-0.2.3}/docs/stylesheets/extra.css +24 -0
- {webagents-0.2.2 → webagents-0.2.3}/mkdocs.yml +8 -1
- {webagents-0.2.2 → webagents-0.2.3}/pyproject.toml +9 -20
- {webagents-0.2.2 → webagents-0.2.3}/requirements.txt +1 -0
- webagents-0.2.3/tests/agents/core/test_handoffs.py +751 -0
- webagents-0.2.3/tests/test_replicate_skill.py +530 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/__init__.py +9 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/core/base_agent.py +865 -69
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/core/handoffs.py +14 -6
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/base.py +33 -2
- webagents-0.2.3/webagents/agents/skills/core/llm/litellm/skill.py +1417 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/vector_memory/skill.py +8 -16
- webagents-0.2.3/webagents/agents/skills/ecosystem/openai/__init__.py +6 -0
- webagents-0.2.3/webagents/agents/skills/ecosystem/openai/skill.py +867 -0
- webagents-0.2.3/webagents/agents/skills/ecosystem/replicate/README.md +440 -0
- webagents-0.2.3/webagents/agents/skills/ecosystem/replicate/__init__.py +10 -0
- webagents-0.2.3/webagents/agents/skills/ecosystem/replicate/skill.py +517 -0
- webagents-0.2.3/webagents/agents/skills/examples/__init__.py +6 -0
- webagents-0.2.3/webagents/agents/skills/examples/music_player.py +329 -0
- webagents-0.2.3/webagents/agents/skills/robutler/handoff/__init__.py +6 -0
- webagents-0.2.3/webagents/agents/skills/robutler/handoff/skill.py +191 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/nli/skill.py +180 -24
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/payments/exceptions.py +27 -7
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/payments/skill.py +64 -14
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/files/skill.py +2 -2
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/tools/decorators.py +243 -47
- webagents-0.2.3/webagents/agents/widgets/__init__.py +6 -0
- webagents-0.2.3/webagents/agents/widgets/renderer.py +150 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/core/app.py +130 -15
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/core/models.py +1 -1
- {webagents-0.2.2 → webagents-0.2.3}/webagents/utils/logging.py +13 -1
- webagents-0.2.2/docs/agent/handoffs.md +0 -373
- webagents-0.2.2/webagents/agents/skills/core/llm/litellm/skill.py +0 -538
- webagents-0.2.2/webagents/utils/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/.github/workflows/ci.yml +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/.github/workflows/docs.yml +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/.github/workflows/publish.yml +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/.vscode/settings.json +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/CONTRIBUTING.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/LICENSE +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/RELEASE.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/agent/lifecycle.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Circle_Icon_W.png +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Robutler_Logo_300.png +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Robutler_Logo_Full.png +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Robutler_OG_Card_B.png +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Robutler_OG_Card_Nvidia_Yel.png +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/assets/robutler-logo.svg +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/assets/robutler_logo.png +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/blog/.authors.yml +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/blog/index.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/developers/contributing.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/developers/development.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/dynamic-agents.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/gen_ref_pages.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/javascripts/mathjax.js +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/license.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/quickstart.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/requirements.txt +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/server-architecture.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/core/llm.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/core/mcp.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/core/memory.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/overview.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/auth.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/discovery.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/nli.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/examples/minimal_quickstart.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/examples/server_demo.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/examples/simple_demo.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/pytest.ini +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/requirements-ecosystem.txt +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_base_agent_http.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_base_agent_init.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_base_agent_quick.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_base_agent_scopes.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_http_capabilities_integration.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/fixtures/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/integration_config.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/openai_integration_config.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_discovery_skill_integration.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_dynamic_agents_integration.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_external_tools_integration.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_integration_litellm.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_integration_openai.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_payment_skill_integration.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/run_http_tests.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/conftest.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_dynamic_agents.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_http_server_integration.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_models.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_monitoring.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_server_core.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_server_streaming.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_streaming_compliance.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_tool_execution.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/skills/core/conftest.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/skills/core/mcp_test_config.json +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/skills/core/test_mcp_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/skills/core/test_mcp_skill_backup.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_auth_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_basic_agent.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_crewai_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_decorators.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_discovery_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_litellm_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_long_term_memory_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_memory_skills.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_mongodb_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_n8n_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_nli_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_payment_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_planner_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_prompt_decorator.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_supabase_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_vector_memory_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_webagents_storage_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_x_com.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/tests/test_zapier_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/__main__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/core/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/handoffs/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/interfaces/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/lifecycle/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/guardrails/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/anthropic/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/litellm/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/openai/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/xai/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/mcp/README.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/mcp/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/mcp/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/long_term_memory/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/long_term_memory/memory_skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/short_term_memory/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/short_term_memory/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/planning/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/planning/planner.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/crewai/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/crewai/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/database/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/database/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/filesystem/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/google/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/google/calendar/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/google/calendar/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/mongodb/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/mongodb/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/n8n/README.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/n8n/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/n8n/skill.py +0 -0
- {webagents-0.2.2/webagents/agents/skills/ecosystem/openai_agents → webagents-0.2.3/webagents/agents/skills/ecosystem/web}/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/x_com/README.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/x_com/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/x_com/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/zapier/README.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/zapier/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/zapier/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/auth/README.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/auth/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/auth/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/crm/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/crm/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/discovery/README.md +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/discovery/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/discovery/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/kv/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/kv/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/message_history/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/message_history/skill.py +0 -0
- {webagents-0.2.2/webagents/agents/skills/ecosystem/web → webagents-0.2.3/webagents/agents/skills/robutler/messages}/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/nli/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/notifications/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/notifications/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/payments/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/files/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/json/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/json/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/kv/skill.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage.py +0 -0
- {webagents-0.2.2/webagents/agents/skills/robutler/messages → webagents-0.2.3/webagents/agents/tools}/__init__.py +0 -0
- {webagents-0.2.2/webagents/agents/tools → webagents-0.2.3/webagents/agents/tracing}/__init__.py +0 -0
- {webagents-0.2.2/webagents/agents/tracing → webagents-0.2.3/webagents/agents/workflows}/__init__.py +0 -0
- {webagents-0.2.2/webagents/agents/workflows → webagents-0.2.3/webagents/scripts}/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/__init__.py +0 -0
- {webagents-0.2.2/webagents/scripts → webagents-0.2.3/webagents/server/context}/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/context/context_vars.py +0 -0
- {webagents-0.2.2/webagents/server/context → webagents-0.2.3/webagents/server/core}/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/core/middleware.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/core/monitoring.py +0 -0
- {webagents-0.2.2/webagents/server/core → webagents-0.2.3/webagents/server/endpoints}/__init__.py +0 -0
- {webagents-0.2.2/webagents/server/endpoints → webagents-0.2.3/webagents/server/interfaces}/__init__.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/middleware.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/models.py +0 -0
- {webagents-0.2.2 → webagents-0.2.3}/webagents/server/monitoring.py +0 -0
- {webagents-0.2.2/webagents/server/interfaces → webagents-0.2.3/webagents/utils}/__init__.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: webagents
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.3
|
4
4
|
Summary: Foundation framework for the Web of Agents - build, serve and monetize AI agents
|
5
5
|
Author: Awesome Opensource Contributors and Robutler Team
|
6
6
|
License: MIT License
|
@@ -26,41 +26,29 @@ License: MIT License
|
|
26
26
|
License-File: LICENSE
|
27
27
|
Requires-Python: >=3.10
|
28
28
|
Requires-Dist: colorama>=0.4.6
|
29
|
+
Requires-Dist: crewai>=0.1.0
|
29
30
|
Requires-Dist: fastapi>=0.100.0
|
30
31
|
Requires-Dist: fastmcp>=2.3.0
|
31
32
|
Requires-Dist: httpx>=0.24.0
|
32
33
|
Requires-Dist: litellm>=1.0.0
|
33
34
|
Requires-Dist: pillow>=10.0.0
|
35
|
+
Requires-Dist: psycopg2-binary>=2.9.0
|
34
36
|
Requires-Dist: pydantic-settings>=2.0.0
|
35
37
|
Requires-Dist: pydantic>=2.7.0
|
38
|
+
Requires-Dist: pymongo>=4.0.0
|
36
39
|
Requires-Dist: python-dotenv>=1.0.0
|
40
|
+
Requires-Dist: supabase>=2.0.0
|
37
41
|
Requires-Dist: tiktoken>=0.5.0
|
42
|
+
Requires-Dist: tweepy>=4.14.0
|
38
43
|
Requires-Dist: uvicorn>=0.23.0
|
39
|
-
Provides-Extra: crewai
|
40
|
-
Requires-Dist: crewai>=0.1.0; extra == 'crewai'
|
41
44
|
Provides-Extra: dev
|
42
45
|
Requires-Dist: black>=23.0.0; extra == 'dev'
|
43
46
|
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
44
47
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
45
48
|
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
46
49
|
Requires-Dist: ruff>=0.0.270; extra == 'dev'
|
47
|
-
Provides-Extra: ecosystem
|
48
|
-
Requires-Dist: crewai>=0.1.0; extra == 'ecosystem'
|
49
|
-
Requires-Dist: httpx>=0.24.0; extra == 'ecosystem'
|
50
|
-
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'ecosystem'
|
51
|
-
Requires-Dist: pymongo>=4.0.0; extra == 'ecosystem'
|
52
|
-
Requires-Dist: supabase>=2.0.0; extra == 'ecosystem'
|
53
|
-
Requires-Dist: tweepy>=4.14.0; extra == 'ecosystem'
|
54
50
|
Provides-Extra: examples
|
55
51
|
Requires-Dist: openai-agents>=0.0.16; extra == 'examples'
|
56
|
-
Provides-Extra: mongodb
|
57
|
-
Requires-Dist: pymongo>=4.0.0; extra == 'mongodb'
|
58
|
-
Provides-Extra: postgresql
|
59
|
-
Requires-Dist: psycopg2-binary>=2.9.0; extra == 'postgresql'
|
60
|
-
Provides-Extra: supabase
|
61
|
-
Requires-Dist: supabase>=2.0.0; extra == 'supabase'
|
62
|
-
Provides-Extra: twitter
|
63
|
-
Requires-Dist: tweepy>=4.14.0; extra == 'twitter'
|
64
52
|
Description-Content-Type: text/markdown
|
65
53
|
|
66
54
|
# WebAgents - core framework for the Web of Agents
|
@@ -88,16 +76,11 @@ With WebAgents delegation, your agent is as powerful as the whole ecosystem, and
|
|
88
76
|
## 📦 Installation
|
89
77
|
|
90
78
|
```bash
|
91
|
-
# Core framework
|
92
79
|
pip install webagents
|
93
|
-
|
94
|
-
# With ecosystem skills (MongoDB, Supabase, CrewAI, X.com, etc.)
|
95
|
-
pip install webagents[ecosystem]
|
96
|
-
|
97
|
-
# Individual skills
|
98
|
-
pip install webagents[mongodb,crewai,twitter]
|
99
80
|
```
|
100
81
|
|
82
|
+
WebAgents includes everything you need: core framework, LLM integration, and ecosystem skills (MongoDB, Supabase, PostgreSQL, CrewAI, X.com, etc.)
|
83
|
+
|
101
84
|
## 🏃♂️ Quick Start
|
102
85
|
|
103
86
|
### Create Your First Agent
|
@@ -23,16 +23,11 @@ With WebAgents delegation, your agent is as powerful as the whole ecosystem, and
|
|
23
23
|
## 📦 Installation
|
24
24
|
|
25
25
|
```bash
|
26
|
-
# Core framework
|
27
26
|
pip install webagents
|
28
|
-
|
29
|
-
# With ecosystem skills (MongoDB, Supabase, CrewAI, X.com, etc.)
|
30
|
-
pip install webagents[ecosystem]
|
31
|
-
|
32
|
-
# Individual skills
|
33
|
-
pip install webagents[mongodb,crewai,twitter]
|
34
27
|
```
|
35
28
|
|
29
|
+
WebAgents includes everything you need: core framework, LLM integration, and ecosystem skills (MongoDB, Supabase, PostgreSQL, CrewAI, X.com, etc.)
|
30
|
+
|
36
31
|
## 🏃♂️ Quick Start
|
37
32
|
|
38
33
|
### Create Your First Agent
|
@@ -12,8 +12,7 @@ Expose custom HTTP API endpoints for your agent using the `@http` decorator. End
|
|
12
12
|
Define an endpoint and attach it to your agent via `capabilities` (auto-registration):
|
13
13
|
|
14
14
|
```python
|
15
|
-
from webagents
|
16
|
-
from webagents.agents.tools.decorators import http
|
15
|
+
from webagents import BaseAgent, http
|
17
16
|
|
18
17
|
@http("/status", method="get")
|
19
18
|
def get_status() -> dict:
|
@@ -42,7 +41,7 @@ Available at:
|
|
42
41
|
## Methods, Path and Query
|
43
42
|
|
44
43
|
```python
|
45
|
-
from webagents
|
44
|
+
from webagents import http
|
46
45
|
|
47
46
|
# GET collection
|
48
47
|
@http("/users", method="get")
|
@@ -0,0 +1,409 @@
|
|
1
|
+
# Agent Handoffs
|
2
|
+
|
3
|
+
The handoff system provides a unified interface for both local LLM completions and remote agent handoffs, with automatic streaming support and priority-based handler selection.
|
4
|
+
|
5
|
+
Handoffs enable seamless completion handling through a unified interface that supports:
|
6
|
+
|
7
|
+
- **Local LLM completions** (via LiteLLM, OpenAI, etc.)
|
8
|
+
- **Remote agent handoffs** - Delegate to specialized agents with full streaming support
|
9
|
+
- **Automatic streaming/non-streaming adaptation**
|
10
|
+
- **Priority-based handler selection**
|
11
|
+
- **Dynamic prompt injection**
|
12
|
+
|
13
|
+
## Handoff System Overview
|
14
|
+
|
15
|
+
The handoff system provides a flexible, decorator-based approach for registering completion handlers:
|
16
|
+
|
17
|
+
```python
|
18
|
+
from webagents import Skill, handoff
|
19
|
+
|
20
|
+
class CustomLLMSkill(Skill):
|
21
|
+
"""Custom LLM completion handler"""
|
22
|
+
|
23
|
+
async def initialize(self, agent):
|
24
|
+
# Register as handoff handler
|
25
|
+
# NOTE: Register streaming function for best compatibility
|
26
|
+
agent.register_handoff(
|
27
|
+
Handoff(
|
28
|
+
target="custom_llm",
|
29
|
+
description="Custom LLM using specialized model",
|
30
|
+
scope="all",
|
31
|
+
metadata={
|
32
|
+
'function': self.chat_completion_stream,
|
33
|
+
'priority': 10,
|
34
|
+
'is_generator': True # Streaming generator
|
35
|
+
}
|
36
|
+
),
|
37
|
+
source="custom_llm"
|
38
|
+
)
|
39
|
+
|
40
|
+
async def chat_completion_stream(
|
41
|
+
self,
|
42
|
+
messages: List[Dict[str, Any]],
|
43
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
44
|
+
**kwargs
|
45
|
+
) -> AsyncGenerator[Dict[str, Any], None]:
|
46
|
+
"""Handle LLM completion (streaming)"""
|
47
|
+
async for chunk in self.my_streaming_llm_api(messages, tools):
|
48
|
+
yield chunk
|
49
|
+
```
|
50
|
+
|
51
|
+
## Core Concepts
|
52
|
+
|
53
|
+
### Handoff Dataclass
|
54
|
+
|
55
|
+
```python
|
56
|
+
from webagents.agents.skills.base import Handoff
|
57
|
+
|
58
|
+
Handoff(
|
59
|
+
target: str, # Handler identifier
|
60
|
+
description: str = "", # Description/prompt for when to use
|
61
|
+
scope: Union[str, List[str]] = "all",
|
62
|
+
metadata: Dict[str, Any] = None # Contains: function, priority, is_generator
|
63
|
+
)
|
64
|
+
```
|
65
|
+
|
66
|
+
### Priority System
|
67
|
+
|
68
|
+
Handoffs are selected based on priority (lower = higher priority):
|
69
|
+
|
70
|
+
- **Priority 10**: Local LLM handlers (default)
|
71
|
+
- **Priority 20**: Remote agent handlers
|
72
|
+
- **Priority 50+**: Custom/specialized handlers
|
73
|
+
|
74
|
+
The **first registered handoff** (lowest priority) becomes the **default completion handler**.
|
75
|
+
|
76
|
+
### Streaming vs Non-Streaming
|
77
|
+
|
78
|
+
The system automatically adapts handlers:
|
79
|
+
|
80
|
+
- **Async generators** (`async def func() -> AsyncGenerator`) = streaming native
|
81
|
+
- **Regular async functions** (`async def func() -> Dict`) = non-streaming native
|
82
|
+
- **Automatic adaptation** in both directions
|
83
|
+
|
84
|
+
## Dynamic Handoff Invocation
|
85
|
+
|
86
|
+
Skills can allow the LLM to explicitly choose to use their handoff during conversation, enabling dynamic switching between handlers:
|
87
|
+
|
88
|
+
### Using request_handoff Helper
|
89
|
+
|
90
|
+
```python
|
91
|
+
from webagents import Skill, tool, handoff
|
92
|
+
|
93
|
+
class SpecialistSkill(Skill):
|
94
|
+
@handoff(name="specialist", prompt="Specialized handler", priority=15)
|
95
|
+
async def specialist_handler(self, messages, tools, **kwargs):
|
96
|
+
# Handle requests...
|
97
|
+
async for chunk in process_with_specialist(messages):
|
98
|
+
yield chunk
|
99
|
+
|
100
|
+
@tool(description="Switch to specialist for advanced queries")
|
101
|
+
async def use_specialist(self) -> str:
|
102
|
+
return self.request_handoff("specialist")
|
103
|
+
```
|
104
|
+
|
105
|
+
When the LLM calls `use_specialist()`, the framework:
|
106
|
+
1. Detects the handoff request marker
|
107
|
+
2. Finds the registered `specialist` handoff
|
108
|
+
3. Executes it with the current conversation
|
109
|
+
4. Streams the response directly to the user
|
110
|
+
|
111
|
+
This works with both local and remote handoffs, enabling the LLM to dynamically route requests to the most appropriate handler.
|
112
|
+
|
113
|
+
### Handoff Chaining and Default Reset
|
114
|
+
|
115
|
+
When a dynamic handoff is invoked:
|
116
|
+
|
117
|
+
1. **The handoff executes** with the current conversation context
|
118
|
+
2. **Streaming is continuous** - the response streams directly to the user
|
119
|
+
3. **The agent resets to the default handoff** after the turn completes
|
120
|
+
4. **Next user message** uses the default handoff again (unless another dynamic handoff is requested)
|
121
|
+
|
122
|
+
This ensures that dynamic handoffs are **temporary switches** for specific requests, not permanent mode changes:
|
123
|
+
|
124
|
+
```python
|
125
|
+
# Turn 1: User: "Use specialist"
|
126
|
+
# → LLM calls use_specialist() → specialist handoff executes → response streams
|
127
|
+
# → After turn ends, active_handoff resets to default (e.g., litellm)
|
128
|
+
|
129
|
+
# Turn 2: User: "What about this?"
|
130
|
+
# → Uses default handoff (litellm) again
|
131
|
+
```
|
132
|
+
|
133
|
+
**Handoff chaining** is also supported - a handoff can request another handoff during its execution, allowing multi-stage processing within a single turn.
|
134
|
+
|
135
|
+
## Using the @handoff Decorator
|
136
|
+
|
137
|
+
### Basic Handoff with Prompt
|
138
|
+
|
139
|
+
```python
|
140
|
+
from webagents import handoff
|
141
|
+
|
142
|
+
class SpecializedSkill(Skill):
|
143
|
+
@handoff(
|
144
|
+
name="specialist",
|
145
|
+
prompt="Use this handler for complex mathematical computations requiring symbolic processing",
|
146
|
+
priority=15
|
147
|
+
)
|
148
|
+
async def specialized_completion(
|
149
|
+
self,
|
150
|
+
messages: List[Dict[str, Any]],
|
151
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
152
|
+
context=None, # Auto-injected if present in signature
|
153
|
+
**kwargs
|
154
|
+
) -> Dict[str, Any]:
|
155
|
+
"""Handle specialized completions"""
|
156
|
+
result = await self.process_with_specialist(messages)
|
157
|
+
return result
|
158
|
+
```
|
159
|
+
|
160
|
+
### Streaming Handoff
|
161
|
+
|
162
|
+
For streaming responses, use an async generator:
|
163
|
+
|
164
|
+
```python
|
165
|
+
class StreamingSkill(Skill):
|
166
|
+
@handoff(
|
167
|
+
name="streaming_llm",
|
168
|
+
prompt="Streaming LLM handler for real-time responses",
|
169
|
+
priority=10
|
170
|
+
)
|
171
|
+
async def streaming_completion(
|
172
|
+
self,
|
173
|
+
messages: List[Dict[str, Any]],
|
174
|
+
tools: Optional[List[Dict[str, Any]]] = None,
|
175
|
+
**kwargs
|
176
|
+
) -> AsyncGenerator[Dict[str, Any], None]:
|
177
|
+
"""Stream LLM responses"""
|
178
|
+
async for chunk in self.my_streaming_api(messages, tools):
|
179
|
+
yield chunk
|
180
|
+
```
|
181
|
+
|
182
|
+
### Context Injection
|
183
|
+
|
184
|
+
The decorator automatically injects `context` if it's in your function signature:
|
185
|
+
|
186
|
+
```python
|
187
|
+
@handoff(name="context_aware", priority=10)
|
188
|
+
async def completion_with_context(
|
189
|
+
self,
|
190
|
+
messages: List[Dict[str, Any]],
|
191
|
+
context=None, # Auto-injected from request context
|
192
|
+
**kwargs
|
193
|
+
) -> Dict[str, Any]:
|
194
|
+
"""Use context for billing, auth, etc."""
|
195
|
+
user_id = context.auth.user_id if context else None
|
196
|
+
return await self.process(messages, user_id=user_id)
|
197
|
+
```
|
198
|
+
|
199
|
+
## Built-in Handoff Skills
|
200
|
+
|
201
|
+
### LiteLLMSkill (Default)
|
202
|
+
|
203
|
+
LiteLLMSkill automatically registers as a handoff handler during initialization:
|
204
|
+
|
205
|
+
```python
|
206
|
+
from webagents.agents.skills.core.llm.litellm import LiteLLMSkill
|
207
|
+
|
208
|
+
# In dynamic_factory.py or your agent setup
|
209
|
+
skills["litellm"] = LiteLLMSkill(model="openai/gpt-4o")
|
210
|
+
|
211
|
+
# LiteLLMSkill.initialize() automatically calls:
|
212
|
+
agent.register_handoff(
|
213
|
+
Handoff(
|
214
|
+
target="litellm_openai_gpt-4o",
|
215
|
+
description="LiteLLM completion handler using openai/gpt-4o",
|
216
|
+
metadata={'function': self.chat_completion_stream, 'priority': 10, 'is_generator': True}
|
217
|
+
),
|
218
|
+
source="litellm"
|
219
|
+
)
|
220
|
+
# NOTE: Registers the streaming function for optimal compatibility in both modes
|
221
|
+
```
|
222
|
+
|
223
|
+
## Remote Agent Handoffs
|
224
|
+
|
225
|
+
**AgentHandoffSkill** enables seamless handoffs to remote agents via NLI with full streaming support. This is essential for multi-agent systems where you want to delegate tasks to specialized agents.
|
226
|
+
|
227
|
+
### Basic Setup
|
228
|
+
|
229
|
+
```python
|
230
|
+
from webagents.agents.skills.robutler.handoff import AgentHandoffSkill
|
231
|
+
from webagents.agents.skills.robutler.nli import NLISkill
|
232
|
+
|
233
|
+
# Setup skills - NLI is required for remote agent communication
|
234
|
+
skills = {
|
235
|
+
"nli": NLISkill(),
|
236
|
+
"agent_handoff": AgentHandoffSkill()
|
237
|
+
}
|
238
|
+
|
239
|
+
agent = BaseAgent(
|
240
|
+
name="coordinator",
|
241
|
+
instructions="Coordinate with specialist agents",
|
242
|
+
skills=skills
|
243
|
+
)
|
244
|
+
```
|
245
|
+
|
246
|
+
### Default Agent Configuration
|
247
|
+
|
248
|
+
You can configure a default agent URL that will be used automatically:
|
249
|
+
|
250
|
+
```python
|
251
|
+
from webagents.agents.skills.robutler.handoff import AgentHandoffSkill
|
252
|
+
|
253
|
+
# Register remote agent handoff with default agent
|
254
|
+
skills["agent_handoff"] = AgentHandoffSkill({
|
255
|
+
'agent_url': 'https://robutler.ai/agents/specialist'
|
256
|
+
})
|
257
|
+
|
258
|
+
# This handoff will automatically use the configured agent
|
259
|
+
# Great for dedicated coordinator → specialist relationships
|
260
|
+
```
|
261
|
+
|
262
|
+
### Calling Remote Agents
|
263
|
+
|
264
|
+
Hand off to specific agents using their full URL (includes agent ID):
|
265
|
+
|
266
|
+
```python
|
267
|
+
# Direct handoff to a remote agent
|
268
|
+
async for chunk in agent.skills['agent_handoff'].remote_agent_handoff(
|
269
|
+
agent_url="https://robutler.ai/agents/96f6d0ab-71d4-4035-a71d-94d1c2b72da3",
|
270
|
+
messages=messages,
|
271
|
+
tools=tools
|
272
|
+
):
|
273
|
+
# Streams OpenAI-compatible chunks in real-time
|
274
|
+
yield chunk
|
275
|
+
```
|
276
|
+
|
277
|
+
### Dynamic Agent Discovery
|
278
|
+
|
279
|
+
You can programmatically discover and call agents:
|
280
|
+
|
281
|
+
```python
|
282
|
+
from webagents import Skill, tool
|
283
|
+
|
284
|
+
class CoordinatorSkill(Skill):
|
285
|
+
@tool(description="Delegate complex music tasks to the music specialist")
|
286
|
+
async def delegate_to_music_agent(self, task: str) -> str:
|
287
|
+
"""Hand off music-related tasks to r-music agent"""
|
288
|
+
# Discover agent (could be from database, config, or API)
|
289
|
+
music_agent_url = "https://robutler.ai/agents/96f6d0ab-71d4-4035-a71d-94d1c2b72da3"
|
290
|
+
|
291
|
+
# Request handoff (framework will stream the response)
|
292
|
+
return self.request_handoff("agent_handoff", agent_url=music_agent_url)
|
293
|
+
```
|
294
|
+
|
295
|
+
### How It Works
|
296
|
+
|
297
|
+
1. **Automatic Registration**: AgentHandoffSkill registers itself with `priority=20` during initialization
|
298
|
+
2. **NLI Communication**: Uses `NLISkill.stream_message()` for SSE streaming from remote agents
|
299
|
+
3. **OpenAI Compatibility**: Returns OpenAI-compatible streaming chunks
|
300
|
+
4. **Tool Support**: Remote agents can use their own tools and skills
|
301
|
+
5. **Payment Integration**: Supports payment token authorization for paid agents
|
302
|
+
|
303
|
+
!!! tip "Agent URLs"
|
304
|
+
Agent URLs must include the full agent ID: `https://robutler.ai/agents/{agent-id}`
|
305
|
+
|
306
|
+
You can find agent IDs in the portal or via the agents API.
|
307
|
+
|
308
|
+
!!! info "Streaming by Default"
|
309
|
+
Remote handoffs always stream responses using SSE (Server-Sent Events), providing real-time feedback to users even for long-running operations.
|
310
|
+
|
311
|
+
## Manual Handoff Registration
|
312
|
+
|
313
|
+
You can also register handoffs manually without decorators:
|
314
|
+
|
315
|
+
```python
|
316
|
+
from webagents.agents.skills.base import Handoff
|
317
|
+
|
318
|
+
class MySkill(Skill):
|
319
|
+
async def initialize(self, agent):
|
320
|
+
# Register handoff manually
|
321
|
+
# NOTE: This example shows non-streaming (is_generator=False)
|
322
|
+
# For LLM handlers, prefer streaming (is_generator=True) as shown above
|
323
|
+
agent.register_handoff(
|
324
|
+
Handoff(
|
325
|
+
target="my_handler",
|
326
|
+
description="My custom completion handler",
|
327
|
+
scope="owner", # Only for owner
|
328
|
+
metadata={
|
329
|
+
'function': self.my_completion_handler,
|
330
|
+
'priority': 15,
|
331
|
+
'is_generator': False # Non-streaming example
|
332
|
+
}
|
333
|
+
),
|
334
|
+
source="my_skill"
|
335
|
+
)
|
336
|
+
|
337
|
+
async def my_completion_handler(self, messages, tools=None, **kwargs):
|
338
|
+
# Non-streaming handler that returns a complete response
|
339
|
+
return await self.process(messages)
|
340
|
+
```
|
341
|
+
|
342
|
+
## Dynamic Prompt Integration
|
343
|
+
|
344
|
+
Handoff prompts automatically integrate with agent system prompts:
|
345
|
+
|
346
|
+
```python
|
347
|
+
@handoff(
|
348
|
+
name="math_expert",
|
349
|
+
prompt="Use this handler for advanced mathematical problems requiring symbolic computation, calculus, or theorem proving",
|
350
|
+
priority=15
|
351
|
+
)
|
352
|
+
async def math_completion(self, messages, **kwargs):
|
353
|
+
return await self.math_engine.solve(messages)
|
354
|
+
```
|
355
|
+
|
356
|
+
The `prompt` parameter serves dual purposes:
|
357
|
+
1. **Description**: Explains when this handoff should be used
|
358
|
+
2. **Dynamic Prompt**: Added to agent's system prompt automatically
|
359
|
+
|
360
|
+
|
361
|
+
## Best Practices
|
362
|
+
|
363
|
+
1. **Priority Selection**
|
364
|
+
- Reserve 1-10 for critical/high-priority handlers
|
365
|
+
- Use 10-20 for standard local/remote handlers
|
366
|
+
- Use 20+ for specialized/conditional handlers
|
367
|
+
|
368
|
+
2. **Streaming Support**
|
369
|
+
- Use async generators for streaming-native handlers
|
370
|
+
- System handles adaptation automatically
|
371
|
+
- Don't mix streaming/non-streaming in one function
|
372
|
+
|
373
|
+
3. **Context Usage**
|
374
|
+
- Add `context=None` to signature for auto-injection
|
375
|
+
- Use for auth, billing, user preferences
|
376
|
+
- Don't modify context, it's read-only
|
377
|
+
|
378
|
+
4. **Error Handling**
|
379
|
+
- Always handle errors in custom handoffs
|
380
|
+
- Provide fallback responses
|
381
|
+
- Log failures for debugging
|
382
|
+
|
383
|
+
5. **Prompt Clarity**
|
384
|
+
- Make handoff prompts specific and actionable
|
385
|
+
- Describe when the handler should be used
|
386
|
+
- Include examples of suitable queries
|
387
|
+
|
388
|
+
## Quick Start Example
|
389
|
+
|
390
|
+
```python
|
391
|
+
from webagents.agents import BaseAgent
|
392
|
+
from webagents.agents.skills.core.llm.litellm import LiteLLMSkill
|
393
|
+
from webagents.agents.skills.robutler.nli import NLISkill
|
394
|
+
from webagents.agents.skills.robutler.handoff import AgentHandoffSkill
|
395
|
+
|
396
|
+
# Create agent with handoff support
|
397
|
+
agent = BaseAgent(
|
398
|
+
name="coordinator",
|
399
|
+
instructions="Coordinate tasks and hand off to specialists when needed",
|
400
|
+
skills={
|
401
|
+
"litellm": LiteLLMSkill(model="openai/gpt-4o"),
|
402
|
+
"nli": NLISkill(),
|
403
|
+
"agent_handoff": AgentHandoffSkill()
|
404
|
+
}
|
405
|
+
)
|
406
|
+
|
407
|
+
# LiteLLMSkill automatically registers as the default handoff handler
|
408
|
+
# AgentHandoffSkill enables remote agent handoffs via NLI
|
409
|
+
```
|
@@ -51,9 +51,20 @@ agent = BaseAgent(
|
|
51
51
|
|
52
52
|
## Available Hooks
|
53
53
|
|
54
|
+
Hooks are executed in the following order during request processing:
|
55
|
+
|
56
|
+
1. **on_connection** - Once per request (initialization)
|
57
|
+
2. **before_llm_call** - Before each LLM call in agentic loop
|
58
|
+
3. **after_llm_call** - After each LLM response in agentic loop
|
59
|
+
4. **on_chunk** - For each streaming chunk (streaming only)
|
60
|
+
5. **before_toolcall** - Before each tool execution
|
61
|
+
6. **after_toolcall** - After each tool execution
|
62
|
+
7. **on_message** - Once per request (before finalization)
|
63
|
+
8. **finalize_connection** - Once per request (cleanup)
|
64
|
+
|
54
65
|
### on_connection
|
55
66
|
|
56
|
-
Called when a new request connection is established.
|
67
|
+
Called once when a new request connection is established.
|
57
68
|
|
58
69
|
Typical responsibilities:
|
59
70
|
- Authentication and identity extraction (e.g., `AuthSkill`)
|
@@ -97,6 +108,50 @@ async def on_message(self, context):
|
|
97
108
|
return context
|
98
109
|
```
|
99
110
|
|
111
|
+
### before_llm_call
|
112
|
+
|
113
|
+
Called before each LLM call in the agentic loop.
|
114
|
+
|
115
|
+
Typical responsibilities:
|
116
|
+
- Message preprocessing and transformation
|
117
|
+
- Multimodal content formatting
|
118
|
+
- Conversation history manipulation
|
119
|
+
|
120
|
+
```python
|
121
|
+
@hook("before_llm_call", priority=5)
|
122
|
+
async def before_llm_call(self, context):
|
123
|
+
"""Preprocess messages before LLM"""
|
124
|
+
messages = context.get('conversation_messages', [])
|
125
|
+
|
126
|
+
# Transform messages (e.g., convert markdown images to multimodal format)
|
127
|
+
processed_messages = self.process_messages(messages)
|
128
|
+
context.set('conversation_messages', processed_messages)
|
129
|
+
|
130
|
+
return context
|
131
|
+
```
|
132
|
+
|
133
|
+
### after_llm_call
|
134
|
+
|
135
|
+
Called after each LLM response in the agentic loop.
|
136
|
+
|
137
|
+
Typical responsibilities:
|
138
|
+
- Response post-processing
|
139
|
+
- Cost tracking per iteration
|
140
|
+
- Response validation
|
141
|
+
|
142
|
+
```python
|
143
|
+
@hook("after_llm_call", priority=10)
|
144
|
+
async def after_llm_call(self, context):
|
145
|
+
"""Process LLM response"""
|
146
|
+
response = context.get('llm_response')
|
147
|
+
|
148
|
+
# Track per-iteration costs
|
149
|
+
usage = response.get('usage', {})
|
150
|
+
await self.track_llm_usage(usage)
|
151
|
+
|
152
|
+
return context
|
153
|
+
```
|
154
|
+
|
100
155
|
### before_toolcall
|
101
156
|
|
102
157
|
Called before executing a tool.
|
@@ -120,7 +120,7 @@ Skills provide modular capabilities:
|
|
120
120
|
Tools are executable functions that extend agent capabilities:
|
121
121
|
|
122
122
|
```python
|
123
|
-
from webagents
|
123
|
+
from webagents import tool
|
124
124
|
|
125
125
|
class MySkill(Skill):
|
126
126
|
@tool
|
@@ -149,19 +149,24 @@ Learn about [available hook events](../skills/overview.md) and the [agent lifecy
|
|
149
149
|
|
150
150
|
### Handoffs
|
151
151
|
|
152
|
-
|
152
|
+
Handoffs enable agents to delegate completions to specialized handlers or remote agents:
|
153
153
|
|
154
154
|
```python
|
155
|
-
from webagents
|
156
|
-
|
157
|
-
class
|
158
|
-
@handoff(
|
159
|
-
|
160
|
-
"
|
161
|
-
|
155
|
+
from webagents import Skill, handoff
|
156
|
+
|
157
|
+
class SpecializedSkill(Skill):
|
158
|
+
@handoff(
|
159
|
+
name="math_expert",
|
160
|
+
prompt="Use for advanced mathematical problems",
|
161
|
+
priority=15
|
162
|
+
)
|
163
|
+
async def math_completion(self, messages, tools=None, **kwargs):
|
164
|
+
"""Handle math-focused completions"""
|
165
|
+
async for chunk in self.specialized_math_llm(messages):
|
166
|
+
yield chunk
|
162
167
|
```
|
163
168
|
|
164
|
-
Explore [handoff patterns](../skills/
|
169
|
+
Explore [handoff patterns](handoffs.md), [agent discovery](../skills/platform/discovery.md), and [remote agent communication](../skills/platform/nli.md).
|
165
170
|
|
166
171
|
## Context Management
|
167
172
|
|
@@ -21,8 +21,7 @@ Prompt functions generate dynamic content that gets added to the agent's system
|
|
21
21
|
### Simple Prompt
|
22
22
|
|
23
23
|
```python
|
24
|
-
from webagents
|
25
|
-
from webagents.agents import BaseAgent
|
24
|
+
from webagents import BaseAgent, prompt
|
26
25
|
|
27
26
|
@prompt()
|
28
27
|
def system_status_prompt(context) -> str:
|