Skip to content

feat(apigee-skills-serving): add reference for Apigee API hub as agent skill catalog#889

Draft
gsjurseth wants to merge 3 commits into
apigee:mainfrom
gsjurseth:feat/add-apigee-skills-serving
Draft

feat(apigee-skills-serving): add reference for Apigee API hub as agent skill catalog#889
gsjurseth wants to merge 3 commits into
apigee:mainfrom
gsjurseth:feat/add-apigee-skills-serving

Conversation

@gsjurseth

Copy link
Copy Markdown

Summary

Adds a new reference under references/apigee-skills-serving demonstrating
how to use Apigee API hub as a versioned, signed catalog of agent skills
(SKILL.md bundles) discoverable and installable by LLM agent runtimes such as
OpenCode, Claude Code, and Gemini CLI.

The contribution is fully self-contained: pipeline runs the hermetic 220-test
Python suite (no live GCP needed), all sources have Apache-2.0 headers,
CODEOWNERS and the root README list the new reference.

Why this fits in references/

API hub is increasingly being used as a discovery surface for things other
than traditional REST APIs (notebooks, prompts, MCP toolsets). Agent skills
are a natural fit: small bundles of LLM instructions + helper scripts,
content-addressed and signed. This reference shows the publisher and
consumer contracts end-to-end:

  • Publisher side: pack, sign (Ed25519 over canonical YAML), upload
    to GCS, register with API hub, update_taxonomy for the four user-defined
    attributes (skill-compatible, skill-runtime-iam, skill-signing-key-id,
    skill-bundle-gs-uri).
  • Consumer side: documented contract; the test suite includes a stateful
    in-process integration of register + fetch that exercises it end-to-end
    without contacting GCP.

What's included

Path Purpose
scripts/ Publisher toolchain (5 Python scripts + shared common/ libs)
schema/skill-manifest.schema.yaml Locked v1 manifest schema with Ed25519 signature support
skills/currency-converter/, weather-lookup/ Minimal example skills
skills/apigee-policy-top10/ Non-trivial skill: documents Apigee policy patterns + enumerates deployed policies
examples/apigee-proxy-skill/ Production-shaped showcase: MCP server that scaffolds Apigee proxies
bin/ Operator helpers: check-prerequisites.sh, demo-setup.sh, demo-cleanup.sh
docs/ Architecture overview, publish/install walkthrough, policy-skill deep-dive
tests/ 220 hermetic tests (~1.3s runtime, no live GCP), runs in any Python 3.11+ env
pipeline.sh devrel CI entry-point (creates venv, runs pytest -q)

Verification

  • pipeline.sh runs green locally: 220/220 tests pass in a fresh venv.
  • shellcheck bin/*.sh pipeline.sh: zero errors/warnings, only 3 SC2015
    info notices on intentional counter-idioms.
  • ✅ All Python compiles cleanly (python3 -m py_compile).
  • ✅ All YAML parses cleanly (yaml.safe_load).
  • ✅ All source files carry an Apache-2.0 header.
  • ✅ CODEOWNERS entry added.
  • ✅ Root README updated to list the new reference.

Notes for reviewers

  1. Scope. This is larger than a typical references/ entry (~10k LOC,
    mostly Python tests). I sized it down from the upstream development repo
    by dropping the consumer-side skill-finder runtime and 6 test files
    that hard-depend on it; the publisher contract is fully validated by the
    remaining 220 tests including a stateful in-process register/fetch
    round-trip. Happy to split into smaller PRs if preferred.

  2. No live cloud needed for CI. Every HTTP call, ADC lookup, and GCP
    service is mocked at the requests/google.auth boundary. A reviewer
    can run ./pipeline.sh on their laptop without an Apigee org or API
    hub instance and see all 220 tests pass.

  3. examples/apigee-proxy-skill/ ships a signed manifest with signing
    fields stripped
    — the signature, signing_key_id, zip_sha256, and
    gs_uri fields are removed because they referenced an internal demo
    bucket. Users regenerate them by running scripts/sign_skill.py +
    scripts/upload_skill.py. A comment at the top of each manifest
    documents this.

  4. SKILL.md format. This follows the OpenCode convention
    (~/.config/opencode/skills/{name}/), which is the closest thing to an
    emerging de-facto standard in the OSS agent runtime space. The
    reference is runtime-agnostic; any agent that can read frontmatter +
    markdown + invoke scripts can consume these skills.

  5. CLA. I'm a Googler and have signed the corporate CLA.

Drafting this PR

Opening as draft to give the apigee/devrel maintainers a chance to react
to the scope before the formal review starts. Per CONTRIBUTING.md's guidance
on large PRs, please flag if you'd prefer this discussed as an issue first
or split into smaller chunks.

Checklist

  • pipeline.sh runs locally
  • Apache 2.0 license header on all source files
  • CODEOWNERS entry
  • Listed in root README
  • Conventional Commits commit message
  • mega-linter pass (CI will run on push)
  • CLA verified by CI

…t skill catalog

Adds a new reference implementation under references/apigee-skills-serving
demonstrating how to use Apigee API hub as a versioned, signed catalog of
agent skills (SKILL.md bundles) discoverable and installable by LLM agent
runtimes such as OpenCode, Claude Code, and Gemini CLI.

What's included:

* Publisher toolchain (scripts/): pack/sign/upload/register/update-taxonomy
  Python scripts that turn a directory of SKILL.md + manifest.yaml into a
  signed .skill archive uploaded to GCS and registered with API hub.
* Locked v1 manifest schema (schema/skill-manifest.schema.yaml) with
  Ed25519 detached-signature support over canonical YAML serialisation.
* Three example skills (skills/): currency-converter, weather-lookup,
  apigee-policy-top10 (a non-trivial skill that documents the ten most
  recommended Apigee policy patterns and enumerates which are deployed
  in your org).
* One showcase example (examples/apigee-proxy-skill): a production-shaped
  skill that scaffolds, validates, packages, and deploys Apigee X / hybrid
  proxies via an MCP server.
* End-to-end documentation (docs/): architecture, publish-and-install
  walkthrough, policy-skill-catalog deep-dive.
* Hermetic test suite (tests/): 220 unit + in-process integration tests,
  all HTTP and ADC mocked, no live GCP needed, runs in ~1.3s.
* pipeline.sh: devrel CI entry-point that installs deps into a venv and
  runs the test suite.

Also updates:
* CODEOWNERS: adds @gsjurseth as owner of the new reference.
* README.md: adds the new reference to the References section.

The implementation is independent of any specific agent runtime; the
SKILL.md format and skill install path (~/.config/opencode/skills/) match
the OpenCode convention, which is the closest thing to an emerging
de-facto standard in the OSS agent runtime space.
@OmidTahouri

Copy link
Copy Markdown
Collaborator

/gcbrun

@apigee-devrel-bot

Copy link
Copy Markdown

Pipeline Report

Pipeline Result Elapsed Wall Time
references/apigee-skills-serving 12s
TOTAL PIPELINE 12s

View details in Cloud Build (permission required)

Commit version: b2c61d9

Two CI fixes from PR apigee#889 first run:

1. PYTHON_ISORT (Lint Codebase job): 12 Python files had import groupings
   that violate isort defaults (multi-line imports that fit on one line;
   trailing blank line after imports). Auto-fixed with `isort scripts/ tests/`.

2. License Headers job: 16 files in tests/ were missing the Apache 2.0
   header. (My earlier bulk-header script targeted scripts/ and skills/
   only; tests/ was overlooked.) All 16 now have the standard header.

Verified locally:
- isort --check-only scripts/ tests/  (clean)
- pytest -q tests/  (220/220 pass)
@OmidTahouri

Copy link
Copy Markdown
Collaborator

/gcbrun

@apigee-devrel-bot

Copy link
Copy Markdown

Pipeline Report

Pipeline Result Elapsed Wall Time
references/apigee-skills-serving 11s
TOTAL PIPELINE 11s

View details in Cloud Build (permission required)

Commit version: eda2aa7

Fixes remaining CI lint failures on PR apigee#889 across four linters:

flake8 (W391, F401, E265, E741):
- Removed trailing blank line from 2 __init__.py files
- Removed 7 unused imports across 5 test files
- Renamed ambiguous variable `l` to `line` in a comprehension
- Moved shebang to line 1 in top10.py (was below license header)

bandit (B311, B405, B314):
- Annotated random.randint() for retry jitter with `# nosec B311`
  (random is not used in a cryptographic context)
- Annotated xml.etree.ElementTree import and ET.fromstring() with
  `# nosec B405` / `# nosec B314` (XML is fetched from authenticated
  Apigee API, not untrusted user input)

yamllint (indentation):
- Re-indented block sequences in 4 manifest.yaml files from 0-indent
  to 2-indent per yamllint default (`keywords:\n  - item` instead of
  `keywords:\n- item`)

Verified locally with CI-matching versions:
- isort 5.9.3 --check-only:  clean
- flake8 7.3.0:               clean
- bandit 1.7.0:               no issues
- yamllint:                   clean
- pytest -q tests/:           220/220 pass
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.

3 participants