fix(skills): resolve registry skills through the runtime's CrewAI+ client (#6658)

* fix(skills): resolve registry skills through the installed AMP client

Skill downloads built their own `PlusAPI` and authenticated it from
`CREWAI_USER_PAT`, the platform integration token, or the saved CLI login.
Managed runtimes have no user credential to offer: they install a client of
their own, which `load_agent_from_repository` already resolves through, so
Agent Repository lookups worked while the skill downloads beside them failed
with 401.

Skills now resolve their client the same way, via `resolve_plus_client()` next
to the hook it reads. A client that can't fetch skills falls back to
environment credentials and warns, so older runtimes behave as they do today.
`resolve_plus_response()` shares the sync/async bridging both lookups need,
since `PlusAPI` is synchronous while managed clients are not.

Version pinning, which the same bug was hiding:

- Registry refs accept `@org/name@version`, and `@org/name@v1.2.0` since people
  write it both ways. `parse_skill_ref()` returns a `SkillRef(org, name,
  version)`; `parse_registry_ref()` keeps its `(org, name)` shape and drops the
  pin, so existing callers are unaffected
- Agent Repository agents record a version per skill, which was parsed off the
  response and dropped. Those pins now travel with the refs, so publishing a
  new version of a skill no longer changes every agent that uses it
- A pinned ref only accepts a project-local copy declaring that version in its
  `metadata.version` frontmatter, and the cache reports a miss when the version
  it recorded differs — so a pin re-resolves rather than loading another
  version. Unpinned refs keep hitting the cache as before
- An unknown pin fails instead of quietly falling back to the newest version

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(skills): reject a blank version pin instead of floating to latest

A blank `version` passed to `download_skill` read as "unpinned" and quietly
resolved the latest version, which is not what a caller supplying one asked
for — and it disagreed with `parse_skill_ref`, which already rejects empty
pins. Not reachable through `resolve_registry_ref` or the Agent Repository
auto-pinning, both of which only ever pass a non-empty version.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* fix(skills): carry the caller's context into the worker thread

When resolve_plus_response bridges an async client from inside a running loop
it runs the coroutine on a worker thread, which starts with empty ContextVars.
A client reading runtime state there — the platform integration token, flow
context — would see defaults rather than the caller's values, which is hard to
diagnose from the resulting auth or routing failure.

Copy the context across, matching how the parallel-summarization bridge in this
module already does it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
João Moura
2026-07-26 13:27:29 -03:00
committed by GitHub
parent bd2cb0f23e
commit cc0759854d
11 changed files with 935 additions and 82 deletions

View File

@@ -221,6 +221,34 @@ agent = Agent(
)
```
### Pin a Version
An unpinned reference resolves to the newest published version, so publishing a
new version changes every agent that references it. Append `@<version>` to pin
one instead:
```python
agent = Agent(
role="Senior Code Reviewer",
goal="Review pull requests for quality and security issues",
backstory="Staff engineer with expertise in secure coding practices.",
skills=["@acme/code-review@1.2.0"], # pinned; a leading "v" also works
)
```
A pinned reference re-downloads unless the copy it finds is that exact version —
a pin asks for a specific version rather than hinting at one. A cached skill is
matched on the version recorded when it was installed, so it needs nothing in
its frontmatter; a project-local copy under `skills/` has no such record, so it
is matched on `metadata.version` in its `SKILL.md` frontmatter. Pinning an
unpublished version fails rather than falling back to the latest.
<Note>
Agents from the **Agent Repository** are pinned automatically: the repository
records a version alongside each skill it assigns, and the runtime applies those
pins when it loads the agent.
</Note>
### List
```shell Terminal