Skip to content

feat(skills): discover service recommendations in the backend - #3683

Open
AbigailDeng wants to merge 3 commits into
feature/integratefrom
feat/2026-09-29_skill-service-recommendations
Open

AbigailDeng wants to merge 3 commits into
feature/integratefrom
feat/2026-09-29_skill-service-recommendations

Conversation

@AbigailDeng

@AbigailDeng AbigailDeng commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Selecting a Skill should proactively identify services the caller may need. This backend change adds authenticated GET /api/skills/service-recommendations?skillName=..., returning advisory evidence and exact personal/organization UserService instances. It never selects services or changes grants.

Targets feature/integrate. Only backend contracts, implementation, tests and API documentation are included. The Channels consumer is delivered separately in #3679 against feat/2026-08-04_workflow-activity-vnext. Related issue: #3678. Deploy this endpoint before the complete console experience is available; the console keeps manual selection usable if discovery is unavailable.

Ownership and behavior

  • AI.Abstractions.Skills owns protobuf contracts; AI.Core.Skills owns recommendation policy behind ISkillServiceDiscoverySource.
  • The Ornn provider adapts the existing Ornn/NyxID clients under each caller's credential. Mainnet Host handles authentication and HTTP mapping only. There is no shared credential/result cache or persisted inferred dependency state.
  • Evidence is an explicit Ornn service association, exact catalog recommended_skills association, or a whole service name/slug mention in the description/root instructions. Skill content is treated as data and never executed. All recommendations are advisory; existing APIs do not declare exhaustive mandatory dependencies. Literal matching may miss aliases or include incidental mentions.
  • Exact UserService IDs remain the authorization identities. Account access does not imply current bearer/channel authorization or credential validity. Catalog IDs, association IDs and slugs cannot substitute for instance IDs.
  • Invalid names return 400; unavailable or malformed upstream discovery returns a sanitized, retryable 502 rather than successful empty/partial results. Caller cancellation propagates, and responses use Cache-Control: no-store.

docs/contracts/skill-service-recommendations.md documents the endpoint, layering, caller isolation, evidence limits and separate integration paths.

Local verification

Validated on backend base 7f6a24572 (origin/feature/integrate):

/Users/abigaildeng/.dotnet/dotnet test test/Aevatar.AI.ToolProviders.Ornn.Tests/Aevatar.AI.ToolProviders.Ornn.Tests.csproj --filter 'FullyQualifiedName~SkillServiceRecommendationTests|FullyQualifiedName~OrnnSkillClientTests' --nologo --verbosity quiet
/Users/abigaildeng/.dotnet/dotnet test test/Aevatar.Capabilities.Tests/Aevatar.Capabilities.Tests.csproj --filter FullyQualifiedName~SkillServiceRecommendationEndpointTests --nologo --verbosity quiet
PATH="/opt/homebrew/opt/python@3.12/libexec/bin:/Users/abigaildeng/.dotnet:$PATH" bash tools/ci/architecture_guards.sh
PATH="/opt/homebrew/opt/python@3.12/libexec/bin:$PATH" bash tools/ci/test_stability_guards.sh
git diff --cached --check

All passed: 34 provider/client tests (6 new discovery cases and 28 existing Ornn client cases), 3 new endpoint tests, architecture guards including docs lint (95 files), test stability guards including 9 meta-tests, and whitespace checks. The test commands compiled affected backend projects, including Mainnet Host.

The nine new backend cases cover evidence precedence and exact instance identity, mismatched Skill identity, missing root instructions, unavailable catalog, cancellation, caller isolation, HTTP mapping, authentication/input rejection and retryable errors. Existing repository compiler/analyzer warnings remain outside this change. No live deployment or authenticated end-to-end smoke test was performed.

NyxID conformance

The endpoint registration changes digest-pinned Mainnet Host source, so the Aevatar manifest is mechanically refreshed to source commit 3da66b8813c03a7b1d87616889dd3ff343dcde1a. Assistant behavior, evaluation evidence and its fixed external source pins are unchanged.

The independent current-main wire baseline is reviewed against NyxID 301fbe732a0f20a3c674184e7ea3408ab62968ab. The six changed upstream files preserve Aevatar's consumed authorization/route contracts. The renamed validate_catalog_credential still parses token-exchange credentials against declared fields; its new call and retained body are checked. Direct/node bearer forwarding moved into proxy_service::forwarded_caller_token, whose owner file and both call sites are now covered. API-key scoped inventory and read-only key listing are also explicitly checked. No production adapter change is needed, and the workflow continues to check current upstream main.

docs/contracts/nyxid-code-execution-conformance/v1/README.md records each reviewed surface and consumer impact. The service-recommendation contract clarifies that restricted Agent Keys see scoped inventory, so an absent instance does not prove the account lacks a connection.

Additional local verification (all passed): 114 API/route-admission cases, 88 code-execution/durable-transport cases, 23 conformance/semantic guard cases, both local conformance modes, docs lint (95 files), and whitespace checks.

/Users/abigaildeng/.dotnet/dotnet test test/Aevatar.AI.Tests/Aevatar.AI.Tests.csproj --filter 'FullyQualifiedName~NyxIdApiAccessContractTests|FullyQualifiedName~NyxIdApiClientExactProxyRoutingTests|FullyQualifiedName~NyxIdCodeExecutionRouteAdmissionPreparerTests' --nologo --verbosity quiet
/Users/abigaildeng/.dotnet/dotnet test test/Aevatar.AI.Infrastructure.ChronoSandbox.Tests/Aevatar.AI.Infrastructure.ChronoSandbox.Tests.csproj --filter 'FullyQualifiedName~NyxIdCodeExecutionPortTests|FullyQualifiedName~NyxIdDurableCodeExecutionPortTests' --nologo --verbosity quiet
PATH="/opt/homebrew/opt/python@3.12/libexec/bin:$PATH" python3 -m unittest tools/ci/tests/test_nyxid_conformance_guard.py tools/ci/tests/test_nyxid_semantic_evaluation.py -v
PATH="/opt/homebrew/opt/python@3.12/libexec/bin:$PATH" bash tools/ci/nyxid_conformance_guard.sh
PATH="/opt/homebrew/opt/python@3.12/libexec/bin:$PATH" bash tools/ci/nyxid_conformance_guard.sh --nyxid-wire-root /tmp/aevatar-3683-nyxid-wire-review
PATH="/opt/homebrew/opt/python@3.12/libexec/bin:$PATH" bash tools/docs/lint.sh
git diff --cached --check

The wire checkout is pinned to the reviewed upstream commit for local reproduction; GitHub continues to fetch main. Both conformance modes were rerun after committing. The earlier source-pin correction also passed the architecture guard after commit in CI's PR range mode:

GITHUB_EVENT_NAME=pull_request GITHUB_BASE_REF=feature/integrate PATH="/opt/homebrew/opt/python@3.12/libexec/bin:/Users/abigaildeng/.dotnet:$PATH" bash tools/ci/architecture_guards.sh

GitHub verified the updated head 2c31b0bc2: current-main-wire-drift and pinned-source-drift both passed. The original conformance failure is resolved.

This branch has not been deployed

No deployments
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