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.
Files changed (238) hide show
  1. {webagents-0.2.2 → webagents-0.2.3}/.gitignore +2 -1
  2. {webagents-0.2.2 → webagents-0.2.3}/PKG-INFO +8 -25
  3. {webagents-0.2.2 → webagents-0.2.3}/README.md +2 -7
  4. {webagents-0.2.2 → webagents-0.2.3}/docs/agent/endpoints.md +2 -3
  5. webagents-0.2.3/docs/agent/handoffs.md +409 -0
  6. {webagents-0.2.2 → webagents-0.2.3}/docs/agent/hooks.md +56 -1
  7. {webagents-0.2.2 → webagents-0.2.3}/docs/agent/overview.md +15 -10
  8. {webagents-0.2.2 → webagents-0.2.3}/docs/agent/prompts.md +1 -2
  9. {webagents-0.2.2 → webagents-0.2.3}/docs/agent/skills.md +109 -11
  10. {webagents-0.2.2 → webagents-0.2.3}/docs/agent/tools.md +10 -11
  11. webagents-0.2.3/docs/agent/widgets.md +494 -0
  12. webagents-0.2.3/docs/assets/openai_widgets.png +0 -0
  13. webagents-0.2.3/docs/assets/widgets.png +0 -0
  14. {webagents-0.2.2 → webagents-0.2.3}/docs/index.md +42 -2
  15. {webagents-0.2.2 → webagents-0.2.3}/docs/server.md +2 -2
  16. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/custom.md +2 -4
  17. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/crewai.md +4 -0
  18. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/database.md +4 -0
  19. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/filesystem.md +4 -0
  20. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/google.md +4 -0
  21. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/index.md +13 -1
  22. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/mongodb.md +4 -0
  23. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/n8n.md +4 -0
  24. webagents-0.2.3/docs/skills/ecosystem/openai.md +481 -0
  25. webagents-0.2.3/docs/skills/ecosystem/replicate.md +129 -0
  26. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/x_com.md +4 -0
  27. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/ecosystem/zapier.md +4 -0
  28. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/files.md +1 -2
  29. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/kv.md +1 -2
  30. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/notifications.md +1 -2
  31. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/payments.md +1 -1
  32. {webagents-0.2.2 → webagents-0.2.3}/docs/stylesheets/extra.css +24 -0
  33. {webagents-0.2.2 → webagents-0.2.3}/mkdocs.yml +8 -1
  34. {webagents-0.2.2 → webagents-0.2.3}/pyproject.toml +9 -20
  35. {webagents-0.2.2 → webagents-0.2.3}/requirements.txt +1 -0
  36. webagents-0.2.3/tests/agents/core/test_handoffs.py +751 -0
  37. webagents-0.2.3/tests/test_replicate_skill.py +530 -0
  38. {webagents-0.2.2 → webagents-0.2.3}/webagents/__init__.py +9 -0
  39. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/core/base_agent.py +865 -69
  40. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/core/handoffs.py +14 -6
  41. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/base.py +33 -2
  42. webagents-0.2.3/webagents/agents/skills/core/llm/litellm/skill.py +1417 -0
  43. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/vector_memory/skill.py +8 -16
  44. webagents-0.2.3/webagents/agents/skills/ecosystem/openai/__init__.py +6 -0
  45. webagents-0.2.3/webagents/agents/skills/ecosystem/openai/skill.py +867 -0
  46. webagents-0.2.3/webagents/agents/skills/ecosystem/replicate/README.md +440 -0
  47. webagents-0.2.3/webagents/agents/skills/ecosystem/replicate/__init__.py +10 -0
  48. webagents-0.2.3/webagents/agents/skills/ecosystem/replicate/skill.py +517 -0
  49. webagents-0.2.3/webagents/agents/skills/examples/__init__.py +6 -0
  50. webagents-0.2.3/webagents/agents/skills/examples/music_player.py +329 -0
  51. webagents-0.2.3/webagents/agents/skills/robutler/handoff/__init__.py +6 -0
  52. webagents-0.2.3/webagents/agents/skills/robutler/handoff/skill.py +191 -0
  53. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/nli/skill.py +180 -24
  54. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/payments/exceptions.py +27 -7
  55. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/payments/skill.py +64 -14
  56. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/files/skill.py +2 -2
  57. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/tools/decorators.py +243 -47
  58. webagents-0.2.3/webagents/agents/widgets/__init__.py +6 -0
  59. webagents-0.2.3/webagents/agents/widgets/renderer.py +150 -0
  60. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/core/app.py +130 -15
  61. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/core/models.py +1 -1
  62. {webagents-0.2.2 → webagents-0.2.3}/webagents/utils/logging.py +13 -1
  63. webagents-0.2.2/docs/agent/handoffs.md +0 -373
  64. webagents-0.2.2/webagents/agents/skills/core/llm/litellm/skill.py +0 -538
  65. webagents-0.2.2/webagents/utils/__init__.py +0 -0
  66. {webagents-0.2.2 → webagents-0.2.3}/.github/workflows/ci.yml +0 -0
  67. {webagents-0.2.2 → webagents-0.2.3}/.github/workflows/docs.yml +0 -0
  68. {webagents-0.2.2 → webagents-0.2.3}/.github/workflows/publish.yml +0 -0
  69. {webagents-0.2.2 → webagents-0.2.3}/.vscode/settings.json +0 -0
  70. {webagents-0.2.2 → webagents-0.2.3}/CONTRIBUTING.md +0 -0
  71. {webagents-0.2.2 → webagents-0.2.3}/LICENSE +0 -0
  72. {webagents-0.2.2 → webagents-0.2.3}/RELEASE.md +0 -0
  73. {webagents-0.2.2 → webagents-0.2.3}/docs/agent/lifecycle.md +0 -0
  74. {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Circle_Icon_W.png +0 -0
  75. {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Robutler_Logo_300.png +0 -0
  76. {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Robutler_Logo_Full.png +0 -0
  77. {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Robutler_OG_Card_B.png +0 -0
  78. {webagents-0.2.2 → webagents-0.2.3}/docs/assets/Robutler_OG_Card_Nvidia_Yel.png +0 -0
  79. {webagents-0.2.2 → webagents-0.2.3}/docs/assets/robutler-logo.svg +0 -0
  80. {webagents-0.2.2 → webagents-0.2.3}/docs/assets/robutler_logo.png +0 -0
  81. {webagents-0.2.2 → webagents-0.2.3}/docs/blog/.authors.yml +0 -0
  82. {webagents-0.2.2 → webagents-0.2.3}/docs/blog/index.md +0 -0
  83. {webagents-0.2.2 → webagents-0.2.3}/docs/developers/contributing.md +0 -0
  84. {webagents-0.2.2 → webagents-0.2.3}/docs/developers/development.md +0 -0
  85. {webagents-0.2.2 → webagents-0.2.3}/docs/dynamic-agents.md +0 -0
  86. {webagents-0.2.2 → webagents-0.2.3}/docs/gen_ref_pages.py +0 -0
  87. {webagents-0.2.2 → webagents-0.2.3}/docs/javascripts/mathjax.js +0 -0
  88. {webagents-0.2.2 → webagents-0.2.3}/docs/license.md +0 -0
  89. {webagents-0.2.2 → webagents-0.2.3}/docs/quickstart.md +0 -0
  90. {webagents-0.2.2 → webagents-0.2.3}/docs/requirements.txt +0 -0
  91. {webagents-0.2.2 → webagents-0.2.3}/docs/server-architecture.md +0 -0
  92. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/core/llm.md +0 -0
  93. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/core/mcp.md +0 -0
  94. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/core/memory.md +0 -0
  95. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/overview.md +0 -0
  96. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/auth.md +0 -0
  97. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/discovery.md +0 -0
  98. {webagents-0.2.2 → webagents-0.2.3}/docs/skills/platform/nli.md +0 -0
  99. {webagents-0.2.2 → webagents-0.2.3}/examples/minimal_quickstart.py +0 -0
  100. {webagents-0.2.2 → webagents-0.2.3}/examples/server_demo.py +0 -0
  101. {webagents-0.2.2 → webagents-0.2.3}/examples/simple_demo.py +0 -0
  102. {webagents-0.2.2 → webagents-0.2.3}/pytest.ini +0 -0
  103. {webagents-0.2.2 → webagents-0.2.3}/requirements-ecosystem.txt +0 -0
  104. {webagents-0.2.2 → webagents-0.2.3}/tests/__init__.py +0 -0
  105. {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_base_agent_http.py +0 -0
  106. {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_base_agent_init.py +0 -0
  107. {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_base_agent_quick.py +0 -0
  108. {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_base_agent_scopes.py +0 -0
  109. {webagents-0.2.2 → webagents-0.2.3}/tests/agents/core/test_http_capabilities_integration.py +0 -0
  110. {webagents-0.2.2 → webagents-0.2.3}/tests/fixtures/__init__.py +0 -0
  111. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/__init__.py +0 -0
  112. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/integration_config.py +0 -0
  113. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/openai_integration_config.md +0 -0
  114. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_discovery_skill_integration.py +0 -0
  115. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_dynamic_agents_integration.py +0 -0
  116. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_external_tools_integration.py +0 -0
  117. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_integration_litellm.py +0 -0
  118. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_integration_openai.py +0 -0
  119. {webagents-0.2.2 → webagents-0.2.3}/tests/integration/test_payment_skill_integration.py +0 -0
  120. {webagents-0.2.2 → webagents-0.2.3}/tests/run_http_tests.py +0 -0
  121. {webagents-0.2.2 → webagents-0.2.3}/tests/server/__init__.py +0 -0
  122. {webagents-0.2.2 → webagents-0.2.3}/tests/server/conftest.py +0 -0
  123. {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_dynamic_agents.py +0 -0
  124. {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_http_server_integration.py +0 -0
  125. {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_models.py +0 -0
  126. {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_monitoring.py +0 -0
  127. {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_server_core.py +0 -0
  128. {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_server_streaming.py +0 -0
  129. {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_streaming_compliance.py +0 -0
  130. {webagents-0.2.2 → webagents-0.2.3}/tests/server/test_tool_execution.py +0 -0
  131. {webagents-0.2.2 → webagents-0.2.3}/tests/skills/core/conftest.py +0 -0
  132. {webagents-0.2.2 → webagents-0.2.3}/tests/skills/core/mcp_test_config.json +0 -0
  133. {webagents-0.2.2 → webagents-0.2.3}/tests/skills/core/test_mcp_skill.py +0 -0
  134. {webagents-0.2.2 → webagents-0.2.3}/tests/skills/core/test_mcp_skill_backup.py +0 -0
  135. {webagents-0.2.2 → webagents-0.2.3}/tests/test_auth_skill.py +0 -0
  136. {webagents-0.2.2 → webagents-0.2.3}/tests/test_basic_agent.py +0 -0
  137. {webagents-0.2.2 → webagents-0.2.3}/tests/test_crewai_skill.py +0 -0
  138. {webagents-0.2.2 → webagents-0.2.3}/tests/test_decorators.py +0 -0
  139. {webagents-0.2.2 → webagents-0.2.3}/tests/test_discovery_skill.py +0 -0
  140. {webagents-0.2.2 → webagents-0.2.3}/tests/test_litellm_skill.py +0 -0
  141. {webagents-0.2.2 → webagents-0.2.3}/tests/test_long_term_memory_skill.py +0 -0
  142. {webagents-0.2.2 → webagents-0.2.3}/tests/test_memory_skills.py +0 -0
  143. {webagents-0.2.2 → webagents-0.2.3}/tests/test_mongodb_skill.py +0 -0
  144. {webagents-0.2.2 → webagents-0.2.3}/tests/test_n8n_skill.py +0 -0
  145. {webagents-0.2.2 → webagents-0.2.3}/tests/test_nli_skill.py +0 -0
  146. {webagents-0.2.2 → webagents-0.2.3}/tests/test_payment_skill.py +0 -0
  147. {webagents-0.2.2 → webagents-0.2.3}/tests/test_planner_skill.py +0 -0
  148. {webagents-0.2.2 → webagents-0.2.3}/tests/test_prompt_decorator.py +0 -0
  149. {webagents-0.2.2 → webagents-0.2.3}/tests/test_supabase_skill.py +0 -0
  150. {webagents-0.2.2 → webagents-0.2.3}/tests/test_vector_memory_skill.py +0 -0
  151. {webagents-0.2.2 → webagents-0.2.3}/tests/test_webagents_storage_skill.py +0 -0
  152. {webagents-0.2.2 → webagents-0.2.3}/tests/test_x_com.py +0 -0
  153. {webagents-0.2.2 → webagents-0.2.3}/tests/test_zapier_skill.py +0 -0
  154. {webagents-0.2.2 → webagents-0.2.3}/webagents/__main__.py +0 -0
  155. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/__init__.py +0 -0
  156. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/core/__init__.py +0 -0
  157. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/handoffs/__init__.py +0 -0
  158. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/interfaces/__init__.py +0 -0
  159. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/lifecycle/__init__.py +0 -0
  160. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/__init__.py +0 -0
  161. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/__init__.py +0 -0
  162. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/guardrails/__init__.py +0 -0
  163. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/__init__.py +0 -0
  164. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/anthropic/__init__.py +0 -0
  165. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/litellm/__init__.py +0 -0
  166. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/openai/__init__.py +0 -0
  167. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/llm/xai/__init__.py +0 -0
  168. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/mcp/README.md +0 -0
  169. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/mcp/__init__.py +0 -0
  170. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/mcp/skill.py +0 -0
  171. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/__init__.py +0 -0
  172. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/long_term_memory/__init__.py +0 -0
  173. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/long_term_memory/memory_skill.py +0 -0
  174. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/short_term_memory/__init__.py +0 -0
  175. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/memory/short_term_memory/skill.py +0 -0
  176. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/planning/__init__.py +0 -0
  177. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/core/planning/planner.py +0 -0
  178. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/__init__.py +0 -0
  179. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/crewai/__init__.py +0 -0
  180. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/crewai/skill.py +0 -0
  181. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/database/__init__.py +0 -0
  182. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/database/skill.py +0 -0
  183. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/filesystem/__init__.py +0 -0
  184. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/google/__init__.py +0 -0
  185. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/google/calendar/__init__.py +0 -0
  186. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/google/calendar/skill.py +0 -0
  187. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/mongodb/__init__.py +0 -0
  188. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/mongodb/skill.py +0 -0
  189. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/n8n/README.md +0 -0
  190. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/n8n/__init__.py +0 -0
  191. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/n8n/skill.py +0 -0
  192. {webagents-0.2.2/webagents/agents/skills/ecosystem/openai_agents → webagents-0.2.3/webagents/agents/skills/ecosystem/web}/__init__.py +0 -0
  193. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/x_com/README.md +0 -0
  194. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/x_com/__init__.py +0 -0
  195. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/x_com/skill.py +0 -0
  196. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/zapier/README.md +0 -0
  197. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/zapier/__init__.py +0 -0
  198. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/ecosystem/zapier/skill.py +0 -0
  199. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/__init__.py +0 -0
  200. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/auth/README.md +0 -0
  201. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/auth/__init__.py +0 -0
  202. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/auth/skill.py +0 -0
  203. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/crm/__init__.py +0 -0
  204. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/crm/skill.py +0 -0
  205. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/discovery/README.md +0 -0
  206. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/discovery/__init__.py +0 -0
  207. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/discovery/skill.py +0 -0
  208. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/kv/__init__.py +0 -0
  209. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/kv/skill.py +0 -0
  210. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/message_history/__init__.py +0 -0
  211. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/message_history/skill.py +0 -0
  212. {webagents-0.2.2/webagents/agents/skills/ecosystem/web → webagents-0.2.3/webagents/agents/skills/robutler/messages}/__init__.py +0 -0
  213. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/nli/__init__.py +0 -0
  214. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/notifications/__init__.py +0 -0
  215. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/notifications/skill.py +0 -0
  216. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/payments/__init__.py +0 -0
  217. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/__init__.py +0 -0
  218. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/files/__init__.py +0 -0
  219. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/json/__init__.py +0 -0
  220. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/json/skill.py +0 -0
  221. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage/kv/skill.py +0 -0
  222. {webagents-0.2.2 → webagents-0.2.3}/webagents/agents/skills/robutler/storage.py +0 -0
  223. {webagents-0.2.2/webagents/agents/skills/robutler/messages → webagents-0.2.3/webagents/agents/tools}/__init__.py +0 -0
  224. {webagents-0.2.2/webagents/agents/tools → webagents-0.2.3/webagents/agents/tracing}/__init__.py +0 -0
  225. {webagents-0.2.2/webagents/agents/tracing → webagents-0.2.3/webagents/agents/workflows}/__init__.py +0 -0
  226. {webagents-0.2.2/webagents/agents/workflows → webagents-0.2.3/webagents/scripts}/__init__.py +0 -0
  227. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/__init__.py +0 -0
  228. {webagents-0.2.2/webagents/scripts → webagents-0.2.3/webagents/server/context}/__init__.py +0 -0
  229. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/context/context_vars.py +0 -0
  230. {webagents-0.2.2/webagents/server/context → webagents-0.2.3/webagents/server/core}/__init__.py +0 -0
  231. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/core/middleware.py +0 -0
  232. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/core/monitoring.py +0 -0
  233. {webagents-0.2.2/webagents/server/core → webagents-0.2.3/webagents/server/endpoints}/__init__.py +0 -0
  234. {webagents-0.2.2/webagents/server/endpoints → webagents-0.2.3/webagents/server/interfaces}/__init__.py +0 -0
  235. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/middleware.py +0 -0
  236. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/models.py +0 -0
  237. {webagents-0.2.2 → webagents-0.2.3}/webagents/server/monitoring.py +0 -0
  238. {webagents-0.2.2/webagents/server/interfaces → webagents-0.2.3/webagents/utils}/__init__.py +0 -0
@@ -103,4 +103,5 @@ venv.bak/
103
103
  # IDE specific files
104
104
  .idea/
105
105
  *.swp
106
- *.swo
106
+ *.swo
107
+ **/.DS_Store
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: webagents
3
- Version: 0.2.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.agents.core.base_agent import BaseAgent
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.agents.tools.decorators import http
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.agents.tools.decorators import tool
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
- Route queries to specialized agents for multi-agent workflows:
152
+ Handoffs enable agents to delegate completions to specialized handlers or remote agents:
153
153
 
154
154
  ```python
155
- from webagents.agents.skills.decorators import handoff
156
-
157
- class MySkill(Skill):
158
- @handoff("expert-agent")
159
- def needs_expert(self, query: str) -> bool:
160
- """Determine if expert needed"""
161
- return "complex" in query
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/overview.md) and [agent discovery](../skills/platform/discovery.md).
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.agents.tools.decorators import prompt
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: