Skip to content

App Capability Discovery: App-first tool & trigger creation (V1: Phase 0-3) - #596

Draft
esafwan wants to merge 23 commits into
developfrom
feature/app-capability-discovery
Draft

App Capability Discovery: App-first tool & trigger creation (V1: Phase 0-3)#596
esafwan wants to merge 23 commits into
developfrom
feature/app-capability-discovery

Conversation

@esafwan

@esafwan esafwan commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements V1 (Phase 0-3) of the App Capability Discovery & App-First Agent Builder plan: replaces "know the dotted Python path" tool creation and "pick from every DocType" trigger creation with an app-scoped capability explorer.

  • Phase 0 — extracted reusable function-descriptor helpers (resolve_function_descriptor, inspect_function_parameters, get_function_metadata) in agent_tool_function.py, behavior-preserving for the existing fetch_tool_parameters_from_code flow.
  • Phase 1 (App -> Action discovery)huf/ai/capabilities/{apps,actions,api}.py + frontend/src/components/capabilities/{AppPicker,CapabilitySearch,ActionDetail,CapabilityCard,CapabilityBadges}.tsx, wired into SelectToolsModal.tsx as a new "From Apps" tab. Discovered-but-new actions always persist as types: "Custom Function" (never "App Provided") to avoid colliding with tool_registry.py's huf_tools sync/orphan-cleanup; already-declared (huf_tools) actions attach the existing synced tool directly instead of duplicating it.
  • Phase 2 (App resource discovery/ranking)huf/ai/capabilities/{resources,ranking}.py + ResourceCard/ResourceDetail.tsx. Three-tier disclosure (recommended via HUF App.exposed_tables -> discovered/ranked -> all), reusing the existing DocType-ownership-via-Module-Def helper (extracted into apps_loader.py).
  • Phase 3 (guided Doc Event trigger)huf/ai/capabilities/events.py (human-labeled event descriptors + a pure Trigger Builder adapter) + EventDetail.tsx, wired into TriggerModal.tsx as a new "From App" guided path that reuses the existing Doc Event form/validation/submit code path.
  • Shared CapabilityDescriptorhuf/ai/capabilities/models.py / frontend/src/types/capability.types.ts, the single normalized shape all three discovery surfaces emit.

All discovery endpoints in huf/ai/capabilities/api.py are gated to System Manager / Huf Admin / Huf Manager. No new runtime Tool/Trigger DocType was introduced — this is a discovery/index layer over the existing Agent Tool Function / Agent Trigger primitives, per the plan's explicit "what not to do" list (no bulk materialization of tools, no arbitrary Python callable exposure, no third-party hooks.py edits, no live-LLM-dependent ranking).

Existing "Tool Library" / "Create New" (manual function path) and the raw Advanced trigger-type/DocType/event picker are left fully functional and untouched.

Test plan

  • bench build --app huf — clean, no TS errors
  • bench migrate — clean
  • 34 new backend unit tests pass: huf.ai.capabilities.tests.{test_actions (6), test_resources (16), test_events (7), test_agent_tool_function_descriptor (5)}
  • python3 -m py_compile clean on every new/changed Python file
  • Independent high-level review pass found and fixed 4 integration bugs (missing function_path fetch breaking the attach-existing-tool path, invalid tool_name slugs from humanized titles, JSON-Schema vs array mismatch in parameters_schema rendering, an internal-key leak in scope=all resource results)
  • Manual click-through of "From Apps" tool creation and "From App" trigger creation in a running site (not yet done — this is a draft PR)

🤖 Generated with multi-agent assistance (Claude Code): ~20 sub-agents across research/backend/frontend/test/review waves, orchestrated in a disposable frappe-multihand bench.

esafwan and others added 22 commits August 9, 2026 08:46
…, ActionDetail, CapabilityCard, CapabilityBadges)
@esafwan

esafwan commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Addressed 2 of the 3 follow-up items from the review noted in the PR description:

  • Ownership check (fc0bd0e4): get_resource_events and preview_trigger_payload now enforce the same app_owns_doctype check describe_resource already had, closing the cross-app doctype gap.
  • Error handling (73d12b8d): ResourceDetail, ActionDetail, AppPicker, CapabilitySearch now .catch() capability API failures — toast via sonner + clear loading state, matching the existing pattern in SelectMCPServersModal.tsx. Previously a failed API call left a permanent spinner.

Both verified: bench build/migrate clean, all 34 backend tests still passing, tsc --noEmit clean.

Left out of this PR on purpose: general whitelisted-method discovery beyond huf_tools-declared paths (plan §7.2's fuller vision). Building a safe enumeration surface for arbitrary whitelisted methods is real, security-sensitive scope on its own — tracked as a separate follow-up rather than rushed into an already-large PR.

…py scan

Extends discover_whitelisted_actions_for_app to also scan an app's api.py /
*_api.py files (an existing naming convention used ~18x in this codebase for
whitelisted HTTP endpoints), not just huf_tools-declared function paths.
Every candidate is still re-verified via get_function_metadata(...,
require_whitelisted=True) before being surfaced, satisfying plan section
18.2's allowlist rule (installed app AND callable AND @frappe.whitelist())
without adding general filesystem/AST scanning.

Also fixes describe_app_action, which previously resolved capability ids via
the limit=50 search_app_actions() results -- with declared actions always
sorted first, huf's 100+ declared actions made every framework-discovered
action undescribable. It now looks up declared/discovered descriptors
directly, unaffected by search pagination limits.

Closes the gap noted in PR #596 as deliberately out of scope.
@esafwan

esafwan commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up: general whitelisted-method discovery for zero-config apps

Closes the gap this PR's description explicitly flagged as out of scope ("general whitelisted-method discovery beyond huf_tools-declared paths").

discover_whitelisted_actions_for_app (huf/ai/capabilities/actions.py) now also scans an app's api.py / *_api.py files — an existing naming convention already used ~18 times in this codebase to mark modules that expose whitelisted HTTP endpoints — via two new helpers:

  • _iter_app_api_module_paths(app_name): enumerates dotted module paths for those files, skipping tests/patches/__pycache__/etc.
  • _iter_module_function_paths(module_path): best-effort imports each module and yields its top-level, non-underscore-prefixed functions actually defined there (not re-exports).

Every candidate from this new surface — exactly like the existing huf_tools-declared surface — is still re-verified via get_function_metadata(function_path, require_whitelisted=True) before being returned, so nothing is exposed beyond real, already-whitelisted /api/method/... endpoints. No filesystem/AST scanning of arbitrary modules was added; a module still has to opt in by name or be referenced from huf_tools. Satisfies plan §7.2 / §18.2's allowlist rule ("installed app AND callable AND @frappe.whitelist()") for zero-config apps.

Bug found and fixed during an independent review pass: describe_app_action previously resolved capability ids via search_app_actions()'s merged-and-limit=50-truncated results, with declared descriptors always sorted first. Since huf has 100+ huf_tools-declared actions, every framework-discovered action was unreachable through describe_app_action even though it was correctly listed by search_app_actions. Fixed by having describe_app_action look up declared/discovered descriptors directly, unaffected by search pagination.

11/11 tests pass in huf.ai.capabilities.tests.test_actions (5 pre-existing + 6 new, including a regression test for the describe_app_action fix), plus the rest of the huf.ai.capabilities.tests package re-verified with no regressions.

Commit: e590a64

esafwan added a commit that referenced this pull request Aug 11, 2026
…iscovery

huf/ai/capabilities.py (chat capability gating, from feat/chat-ux-improvements
on develop) and the huf/ai/capabilities/ package (App Capability Discovery,
PR #596) collided on the same module name once merged together onto
pre-dev-stg -- a Python module and package cannot share a name in the same
parent package. Renamed the discovery package to capability_discovery and
updated every backend import, frontend service call, docstring, and test
mock reference to match; huf.ai.capabilities (the chat-capability module)
is untouched.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant