Official agent skill

Make Python Recipe Deployable

by google in google/adk-recipes

Makes an existing Python recipe deployable: generates the serving files a container needs (Dockerfile, .dockerignore, fastapiapp.py, apputils/a2a.py, apputils/services.py…

OfficialApache-2.0Auto-check: notesDevOps & Cloud

Install Make Python Recipe Deployable

skills CLI
$ npx skills add google/adk-recipes --skill make-python-recipe-deployable -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install google/adk-recipes make-python-recipe-deployable --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/google/adk-recipes.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/make-python-recipe-deployable .claude/skills/make-python-recipe-deployable && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
make-python-recipe-deployable
GitHub stars
10k
Token cost
~6.9k tokens
SKILL.md length
3,465 words
Files
9 (incl. scripts)
Skills in repo
14
Repo updated
First seen
Licence
Apache-2.0

At a glance

Makes an existing Python recipe deployable: generates the serving files a container needs (Dockerfile, .dockerignore, fastapiapp.py, apputils/a2a.py, apputils/services.py…

  • Works in 9 steps: Dry run → Handle gates → Interview → …
  • The user wants to make this recipe deployable
  • SKILL.md covers What "deployable" means here,…, What generating a2a.py does…, Rules for the agent and Pipeline, plus 5 more sections
  • Runs Python scripts from its folder; calls uv and python3

What it does

Make Python Recipe Deployable is an agent skill from google/adk-recipes, published by the product's own GitHub organization. Makes an existing Python recipe deployable: generates the serving files a container needs (Dockerfile, .dockerignore, fastapiapp.py, apputils/a2a.py, apputils/services.py, apputils/reasoningengineadapter.py) and configures the recipe to match (required serving dependencies, the App object in agent.py, the hatch wheel package, manifest.deployable). Interactive by design — it asks the recipe owner about runtime data directories and stops for a human decision when a recipe needs an ADK migration or carries a legacy…

Its SKILL.md is about 6.9k tokens, which your agent loads only when the skill is triggered. The skill folder holds 13 other files, including scripts (for example `resources/templates/app_utils/a2a.py`, `resources/templates/app_utils/reasoning_engine_adapter.py` and `resources/templates/app_utils/services.py`).

It sits in DevOps & Cloud, covering Containers and Infrastructure as code. It works with Python, Docker, Terraform and FastAPI. The repository describes itself as: A collection of agent recipes, reference patterns, and vertical plugins built with Agent Development Kit (ADK). The licence is Apache-2.0.

When your agent uses it

  • The user wants to make this recipe deployable
  • Add a Dockerfile to a recipe
  • Add the serving files
  • Containerize a recipe

Example prompts

  • “make this recipe deployable”
  • “add a Dockerfile to a recipe”
  • “add the serving files”
  • “/make-python-recipe-deployable”

Requirements

  • Python 3
  • Docker

Workflow steps

9 steps, taken from the step headings in SKILL.md.

  1. Dry run
  2. Handle gates
  3. Interview
  4. Apply
  5. Report what changed
  6. Follow-ups (you run these)
  7. Boot check (the real proof)
  8. 5 — Container verification (ask first)
  9. Close out

What it can do on your machine

Read from SKILL.md and the folder at commit c339821. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Ships 1 file in scripts/ (Python), which the agent can run.

    Shell commands in SKILL.md call:

    • uv
    • python3

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md. Its commands use uv, which can reach the network depending on how they are called.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Make Python Recipe Deployable loads about 6.9k tokens when it runs. Until then it costs about 257 tokens; SKILL.md has 3,465 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~257
When it runs · the whole SKILL.md, loaded when a task matches
~6.9k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check: notes

The automated check noted patterns worth knowing about, such as sudo or a known installer.

  • NoteMentions a .env fileSKILL.md:473
    E`, and `.dockerignore` correctly keeps `.env` out of the image.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.

SKILL.md

The full file from google/adk-recipes at commit c339821, republished under its Apache-2.0 licence (© google). 3,465 words, ~6,921 tokens.

Download SKILL.mdSave it as .claude/skills/make-python-recipe-deployable/SKILL.md (or your agent's skills folder). This skill also uses 8 other files; get the full folder from GitHub.
name
make-python-recipe-deployable
description
Makes an existing Python recipe deployable: generates the serving files a container needs (Dockerfile, .dockerignore, fast_api_app.py, app_utils/a2a.py, app_utils/services.py, app_utils/reasoning_engine_adapter.py) and configures the recipe to match (required serving dependencies, the App object in agent.py, the hatch wheel package, manifest.deployable). Interactive by design — it asks the recipe owner about runtime data directories and stops for a human decision when a recipe needs an ADK migration or carries a legacy app_utils generation. When docker is available it offers to PROVE the claim: it builds the generated Dockerfile, runs it, probes it, and refuses to flag a recipe deployable if the container does not come up. Does NOT deploy or write terraform. Use when the user wants to "make this recipe deployable", "add a Dockerfile to a recipe", "add the serving files", "containerize a recipe", "verify the container builds", or prepare a recipe for Cloud Build / Artifact Registry.
metadata.author
Google
metadata.license
Apache-2.0
metadata.version
1.0.0

Make a Python Recipe Deployable

A deployable recipe is one that can be packaged into a container and run as a service. This skill writes the files that requires and configures the recipe to match.

It does not build an image, deploy anything, or provision infrastructure. Image builds happen later via Cloud Build → Artifact Registry; this skill's job ends when the files are correct.

The standard it implements lives in .github/policy.yml under deployability: — the minimum google-adk version, the required dependency list, the required file list, and the legacy app_utils file list. Change the standard there, not in the script.


What "deployable" means here, and the one distinction that matters

deployable in .github/schemas/manifest-schema.json means "can be deployed with one click". Two independent questions decide the outcome:

  1. Does it need infrastructure a human must provision? If yes it is containerized, not one-click deployable.
  2. Did we PROVE the container works, or only assume it?
OutcomeMeaningmanifest.deployable
deployable-verifiedNo bespoke infra, and the image built and served.set to true, on evidence
deployable-unverifiedNo bespoke infra, but nothing built it.set to true, on static checks
containerized-verifiedBuilt and served, but needs backing infra.left unset
containerized-unverifiedNeeds backing infra, and unproven.left unset
verification-failedDocker was usable and the recipe failed.left unset, and a pre-existing flag is retracted
verification-inconclusiveVerification was attempted and defeated by the environment — network, registry, or a runtime that could not exec the image here. It proves nothing, so nothing is retracted. Not the same as -unverified: that means nobody tried, this means you did and should retry.set if static checks earned it
blockedThe run stopped without a usable verdict. Four causes: a gate refused it up front (nothing written); a hard ERROR disqualified the recipe; the skill itself faulted; or verification was deferred pending uv lock — a pause, not a judgement, so re-invoke to finish. Check files_written (only a gate stop guarantees a clean tree) and read container-verify to tell a deferral from a real stop.untouched — EXCEPT that a disqualified recipe has a stale flag retracted. Disqualified means a hard ERROR or no usable app object in agent.py, and the latter records no ERROR — so never infer from the absence of an ERROR that the tree was left alone.

Never describe a containerized result as "deployable" to the user. Setting that flag on a recipe that still needs hand-written terraform puts a false claim in the manifest, which is worse than leaving it unset.

Equally, never describe an -unverified result as proven. It means the files are right by inspection and nobody built the image — which is the normal result on a machine without docker, not a defect.

Why -unverified still sets the flag. Absence of evidence is not evidence of absence. Withholding it whenever docker is missing would judge the recipe by the checker's laptop rather than by its own quality, and this skill's primary user has no container runtime at all. Only a verification that actually failed withholds the flag — a recipe proven broken is not deployable, whatever the static checks said.


What generating a2a.py does and does not prove

Nothing, on its own. These templates were designed assuming the project was scaffolded by agents-cli, and a file named a2a.py does not make an agent behave correctly over A2A. The skill copies and configures; it does not certify. Say so in your summary — do not tell the owner their recipe "supports A2A" because the file exists.


Rules for the agent

  1. Confirm before applying. Always run a dry-run first, show the plan, and get a "yes" before --apply. The skill writes six files and edits three.
  2. Ask the questions in the Interview below before applying — but only the ones the dry-run shows are relevant. Do not interrogate the owner about data directories for a recipe that has none.
  3. Never override a gate on your own. adk-locked-version, adk-version-floor and legacy-app-utils return needs_input and stop the run. Each means a human has to change code. Report the message verbatim and stop; do not go hunting for a way around it.
  4. Never widen an existing version bound to satisfy the standard. The script leaves version specifiers exactly as the recipe wrote them and reports them for confirmation. It does merge in missing extras (google-adk → google-adk[gcp,otel-gcp], same version bound), because the generated code imports what those extras install and the recipe would not start otherwise. Those are different risks: an extra only adds a package's own optional dependencies, while a version rewrite can move the recipe onto code it was never tested against.
  5. Do not overwrite an existing fast_api_app.py without explicit confirmation. An existing one is usually bespoke — long-horizon-harness's is ~400 lines of custom routing. --overwrite exists but is a deliberate choice, not a default.
  6. Run the follow-ups yourself after a successful apply (see Step 5); the script does not, so a failure is attributable to the right step.
  7. Stay inside the recipe. If a run reveals problems in a different recipe, mention them and move on.

Pipeline

Step 0 — Dry run
bash
uv run --no-project --with tomlkit --with 'ruamel.yaml' --with packaging \
  python3 .agents/skills/make-python-recipe-deployable/scripts/make_deployable.py \
  --recipe-dir <RECIPE_DIR>

Prints a JSON report: outcome, agent_package, checks, todos, notes. Nothing is written. Exit code 0 = fine, 1 = a gate needs human input, 2 = error.

Summarise it for the owner. Do not dump the raw JSON.

Step 1 — Handle gates

If any check is needs_input, stop. The three that gate:

  • adk-locked-version — uv.lock resolves google-adk to an older major than the standard requires. The declared specifier may well permit the newer version, which is exactly the trap — in both directions. Re-locking IN PLACE keeps the old major (uv is sticky), so the recipe would ship the new serving dependencies against an ADK that cannot support them; resolving FRESH crosses the major silently, and the agent code has only ever run against the old one. The owner must port the agent first. This script rewrites metadata; it cannot migrate code.
  • adk-version-floor — the specifier itself excludes the required version (a <2.0.0 ceiling, an ==1.31.0 pin). Same conclusion.
  • legacy-app-utils — the package carries the old ASP-era generation (telemetry.py, typing.py, deploy.py, memory_config.py). Filenames do not collide with the new set, but the two wire telemetry and services differently and the existing fast_api_app.py imports the old ones. Generating over the top orphans them or double-wires telemetry. A human decides how to migrate.

Also check already-deployable. If it is report_only, the recipe already serves and you must confirm the owner wants to migrate onto the standard layout before applying — see the advisory at the bottom of this file.

Step 2 — Interview

Ask only what applies. Keep it to one round.

  1. Runtime data directories. Does the agent read anything at runtime that is not in the agent package — assets/, sample_data/, a config file? Those need COPY lines or the container fails at request time, not at build time, which is why a human confirms rather than the skill guessing. Pass them as --data-dirs assets,sample_data.
  2. An existing serving file was found. The dry-run reports each as report_only. Ask whether to keep it (default) or replace it (--overwrite). Show what the existing file does first.
  3. Version bounds that sit below the standard. The report lists any existing requirement it left alone (e.g. google-adk>=2.2.0 against a >=2.6.0 standard). Resolution usually lands on a satisfying version anyway — a2a-sdk>=1.0 forces google-adk>=2.5 on its own — but confirm the owner is happy rather than rewriting their pin.
  4. Deployment region. Nothing in a recipe declares one, and it goes into agents-cli-manifest.yaml, so it is a real decision. Default us-east1 (agents-cli's own). Pass --region us-central1 etc.
  5. Backing infrastructure. If the outcome is containerized, confirm the owner understands manifest.deployable stays unset and why.
Step 3 — Apply
bash
uv run --no-project --with tomlkit --with 'ruamel.yaml' --with packaging \
  python3 .agents/skills/make-python-recipe-deployable/scripts/make_deployable.py \
  --recipe-dir <RECIPE_DIR> --apply [--data-dirs a,b] [--overwrite] \
  [--region us-central1]
Step 4 — Report what changed

List files_written and the checks that moved to fixed.

Step 5 — Follow-ups (you run these)

When the script changes dependencies the lockfile goes stale, and the new files are unformatted. In order:

bash
cd <RECIPE_DIR> && uv lock --python 3.11

--python 3.11 because CI pins it — locking with a newer local interpreter produces a lockfile CI rejects with a misleading "out of date" error.

Run the lock command the report's todos actually give you, and if they give you none, skip it. The report picks between three states rather than always asking for a re-lock:

Report todoStateWhat to run
uv lock --upgrade-package google-adk --python 3.11Pinned below the ADK floorThat command — a plain uv lock here is a no-op
uv lock --python 3.11This run changed dependencies, or uv says the lockfile is out of dateA plain re-lock
no lock todoNothing changed and uv lock --check passesNothing — re-locking would only churn uv.lock

The third row is why an idempotent re-run is quiet. The script asks uv lock --check before staying silent, so an earlier run that added dependencies and never locked still produces the todo.

If adk-locked-version came back report_only, the recipe is pinned below the ADK floor — uv keeps any locked version that still satisfies the declared specifier. The report will hand you this instead:

bash
cd <RECIPE_DIR> && uv lock --upgrade-package google-adk --python 3.11

Then confirm the resolved pair. An ADK below 2.5 alongside a2a-sdk 1.x looks fine in the lockfile and dies at import with cannot import name 'TextPart' from 'a2a.types' — invisible to every static check, and one of the reasons Step 6.5 exists.

bash
# from the REPO ROOT, so the root ruff config wins
uv run ruff format <RECIPE_DIR>/ && uv run ruff check --fix <RECIPE_DIR>/

Then the repo validators:

bash
uv run validate manifest <RECIPE_DIR>
uv run validate structure <RECIPE_DIR>
cd <RECIPE_DIR> && uv run pytest tests/ -q
Step 6 — Boot check (the real proof)

Static checks cannot tell you the recipe actually serves. This can, it needs no container runtime, and it is the closest thing to a correctness oracle the skill has. Run it from inside the recipe after uv sync:

bash
cd <RECIPE_DIR> && uv sync --python 3.11 && uv run --python 3.11 --with httpx python -c "
import warnings; warnings.filterwarnings('ignore')
from fastapi.testclient import TestClient
from <PKG>.fast_api_app import app
with TestClient(app) as c:          # entering runs the lifespan
    print('/list-apps ->', c.get('/list-apps').status_code, c.get('/list-apps').json())
    card = [r.path for r in app.routes if 'well-known' in r.path]
    print('agent card ->', c.get(card[0]).status_code if card else 'NO A2A ROUTES')
"

Expected: /list-apps returns 200 listing the agent package, and the agent card returns 200. Entering the TestClient context is what triggers the lifespan — without it the A2A routes never attach and the check is worthless.

If the agent card 404s or no A2A routes exist, the A2A wiring did not take effect. Report that plainly; do not describe the recipe as A2A-capable.

Warnings about experimental InMemoryCredentialService are expected and harmless.

Step 6.5 — Container verification (ask first)

Step 6 proves the app boots on this machine. This proves the image the recipe will actually be deployed as. It is the only step that turns "we generated a Dockerfile" into evidence, and it is what lets the word "deployable" mean anything.

Look at the docker check in the report. It is present in every run, including the dry-run, and its details.docker_state is one of:

StateMeaningWhat you do
absentNo docker on PATH.Skip. Say nothing alarming — this is the common case, not a problem.
unreachableBinary present, daemon not answering.Skip, same as above. Mention the daemon is down in case they want to start it.
usableDaemon responding.Ask the owner (below).

When and only when the state is usable, ask:

Docker is available. Shall I build the generated Dockerfile and check the container actually serves? It takes a few minutes, and it means manifest.deployable is set on evidence rather than on inspection. If the container does not come up, I will not set the flag.

If they decline, carry on — the outcome ends -unverified and that is a legitimate result. Do not decide for them, and do not skip the question because verification seems slow.

On a "yes", re-invoke with both --apply and --verify-container. --verify-container does not imply --apply — on its own it reports that verification needs the files on disk, and builds nothing:

bash
uv run --no-project --with tomlkit --with 'ruamel.yaml' --with packaging \
  python3 .agents/skills/make-python-recipe-deployable/scripts/make_deployable.py \
  --recipe-dir <RECIPE_DIR> --apply --verify-container [--data-dirs a,b]

Run it after Step 5's uv lock, not before. The Dockerfile runs uv sync --frozen, which cannot succeed until the lockfile matches. If the lockfile is stale the script does not build — it defers manifest.deployable, returns needs_input, and tells you to lock first. That is by design: a build attempted against a stale lockfile fails with an error that looks exactly like a broken template and is not.

What it does: builds for linux/amd64 (Cloud Run's platform), runs the container with the recipe's own .env.example values plus the policy's container_env, polls /list-apps until it answers, then probes the A2A agent card. It removes the container and the image afterwards.

Reading the result:

  • container-build ERROR — the Dockerfile does not build. The check carries a details.hint naming the likely structural cause. Report it and stop; the recipe is not deployable.
  • container-serves ERROR — the image builds but the app does not come up. The log tail is in the message. manifest.deployable was not set.
  • container-a2a REPORT_ONLY — it serves, but the agent card did not return 200. The A2A wiring did not take effect. Say so plainly and do not call the recipe A2A-capable.

⚠️ Running a container is allowlisted, not automatic. Recipes not on deployability.verification.run_allowlist are built only, because some create real cloud resources at import — core/python/cross-session-memory calls client.agent_engines.create() at module scope. A build-only result is reported as unproven, never as a pass. Add a recipe to the allowlist only after reading its package for import-time side effects.

Show full SKILL.md (1,330 more words)Show less
Step 7 — Close out

Walk the report's todos with the owner — .env.example entries for any new variables (the extract-python-environment-variables skill does this), and terraform if the outcome was containerized.

If you created a .venv in the recipe to run Step 6 and it was not there before, remove it.


Deliberately not in scope

Not doneWhy, and what does it instead
Deploying, or pushing an image anywhereOut of scope by decision. Cloud Build builds and Artifact Registry stores the real image. Step 6.5 builds one only to verify its own output, then deletes it — docker is an instrument here, never a deployment mechanism.
Running a container that is not allowlistedSome recipes create real cloud resources at import. Unlisted recipes are built only.
Migrating agent code across an ADK majorA code migration, not a metadata rewrite. Same stance as align-recipe-pyproject.
Merging a legacy app_utils generationNeeds human judgement about telemetry and feedback wiring.
Writing terraformTwo deployable recipes in this repo share zero infrastructure resources; nothing is templatable.
Removing [tool.ruff*], fixing requires-pythonalign-recipe-pyproject
Completing .env.exampleextract-python-environment-variables
Running uv lock, ruff, or the boot checkYou do, in Steps 5-6, so failures are attributable to the right step.

agents-cli-manifest.yaml

Written when deployability.emit_agents_cli_manifest is true (it is).

This file is functional, not decorative. agents-cli uses it as the project-root marker — find_project_root() walks up looking for it — and agents-cli deploy reads create_params.deployment_target to choose how to deploy. Without it, deploy reports "No agents-cli-manifest.yaml found".

The provenance problem — these recipes were never scaffolded by agents-cli — is handled by omitting the fields that would be fiction, not by skipping the file:

OmittedWhy omission beats a value
acli_versionNo scaffold ran. check_cli_version returns early on an absent version; a fabricated one makes the CLI tell the owner to run agents-cli scaffold upgrade on a project that cannot be upgraded.
generated_atNever read by ProjectConfig.from_dict, and asserts an event that did not happen.
base_templateOnly used by upgrade/enhance. Already defaults to adk, so writing it changes nothing.

Everything written is derived from the recipe or from what the skill just generated. Verified against agents-cli 1.4.0's own parser: the project root resolves, every field reads back correctly, and require_agent_directory / require_deployment_target / require_a2a_project all pass.

An existing agents-cli-manifest.yaml is never overwritten.


Templates

resources/templates/ holds the serving files, vendored from agents-cli 1.4.0's scaffold/base_templates/python and scaffold/deployment_targets/{cloud_run,agent_runtime}/python, rendered for the cloud_run target with in-memory sessions, then formatted to this repo's ruff config so generated files pass CI unmodified.

Two placeholders are substituted at copy time:

PlaceholderBecomes
__AGENT_PACKAGE__the recipe's agent package (app, horizon, ...)
__PROJECT_NAME__[project].name from pyproject.toml

Both are valid Python identifiers on purpose, so the templates parse and stay lint-checked in place rather than only after substitution. __AGENT_PACKAGE__ is registered in the root pyproject.toml's known-first-party so isort orders template imports exactly as the rendered output needs them.

Known divergences from agents-cli, all deliberate:

  • The Dockerfile's FROM python:X-slim is rewritten from the recipe's own requires-python floor. The template hardcodes 3.12; recipes here target 3.11, 3.12 and 3.13.
  • reasoning_engine_adapter.py's streaming route duck-types the object it is about to iterate instead of assuming an async generator. streaming_methods merges the operation registry's sync stream bucket with async_stream, so async for over a method from the former raises TypeError: 'async for' requires an object with __aiter__ method, got generator — at request time, only for whoever streams, and never during a build. The sync route already drew exactly this distinction for the "" and async buckets via iscoroutinefunction; the streaming route did not. This is a fix to the vendored source, so re-rendering from a newer agents-cli will silently revert it — re-check the streaming route after any re-render.
  • fast_api_app.py wires reasoning_engine_adapter.py in, which agents-cli does only under agent_runtime. Published recipe images are deployed to Agent Engine through container_spec, and Agent Engine forwards :query and :streamQuery to /api/reasoning_engine and /api/stream_reasoning_engine. Without the adapter the container starts and 404s every call — the cloud_run render passes this skill's own verification (which probes /list-apps) while being unusable on Agent Engine. The adapter imports agentplatform, supplied by google-cloud-aiplatform[agent-engines], hence that entry in required_dependencies.

Since these are vendored, they drift as agents-cli moves. Re-render from a newer agents-cli when the standard changes; do not hand-edit them to fix a single recipe.


Verified end to end

Against real containers

Both taken through the full pipeline including Step 6.5, then reverted. Deployable recipes live under core/ or contrib/; plugins/ is out of scope.

RecipeOutcomeWhat it proves
contrib/python/financial-advisordeployable-verifiedImage builds, /list-apps → 200, agent card → 200, flag set on evidence.
core/python/rag-agent-searchcontainerized-verifiedBuilds and serves, and the flag still correctly stays unset because it needs a datastore. The two axes compose.

Three failures were found by building that no static check saw. All three are the reason this step exists:

  1. financial-advisor crashed on import with no GOOGLE_CLOUD_PROJECT. Its __init__.py does os.environ.setdefault("GOOGLE_CLOUD_PROJECT", project_id) where google.auth.default() yields None without credentials, and setdefault only assigns when the key is absent. Not a recipe defect — Cloud Run always supplies a project — so container_env now models the platform.
  2. rag-agent-search crashed on Gemini(model=None). It reads MODEL_NAME, and .dockerignore correctly keeps .env out of the image. Fixed by load_env_example, which seeds the container from the recipe's own declared environment. Unconfigured is not the same as broken.
  3. rag-agent-search then failed with ImportError: cannot import name 'TextPart' from 'a2a.types' — a genuine incompatibility. It had resolved to google-adk 2.3.0 against a2a-sdk 1.1.2, and adk ≤2.4.0 expects a2a-sdk<0.4. See the warning below; this one is a live trap.

⚠️ uv lock does not raise an already-locked version. uv is sticky: it preserves any locked version that still satisfies the declared specifier, so a recipe declaring google-adk>=2.0.0 stays on whatever it was pinned at. rag-agent-search stayed on 2.3.0 through a plain uv lock and only moved to 2.7.1 under uv lock --upgrade-package google-adk. The coupling the policy leans on (a2a-sdk>=1.0 forcing adk to 2.5+) travels with google-adk's a2a extra, which the required dependency list does not use — so it never constrains resolution.

The adk-locked-version check now states this correctly and emits uv lock --upgrade-package google-adk as the remedy in its details and in the run's todos. Use the command the report gives you, not a plain uv lock, whenever that check is report_only.

Against a live interpreter

plugins/retail/product-search was taken through the pipeline before plugins/ was ruled out of scope for deployability. Kept as the record of what the Step 6 boot check looks like when it works:

  • uv lock resolved to google-adk 2.6.2 + a2a-sdk 1.1.2 — even though the recipe's own bound is >=2.2.0, because a2a-sdk>=1.0 forces google-adk to 2.5+ on its own. That coupling is the reason for the policy floor.
  • All three app_utils modules import.
  • fast_api_app:app builds — 71 routes, no credentials needed.
  • Booted through the lifespan: /list-apps → 200 ['scripts'], and /a2a/scripts/.well-known/agent-card.json → 200.
  • Running the skill a second time wrote nothing and changed no file on disk.

Current recipe landscape

Measured by running the dry-run against every Python recipe under core/ and contrib/ — not predicted. Deployable recipes live in those two trees; plugins under plugins/ are out of scope.

Outcomes below are the dry-run's, so they all end -unverified: a dry run builds nothing. Running with --apply --verify-container on a machine with docker is what upgrades them (financial-advisor and rag-agent-search have both been taken to deployable-verified and containerized-verified).

RecipeDry-run outcomeWhy
contrib/python/financial-advisordeployable-unverifiedloose pin, but locked at 2.6.2
core/python/rag-agent-search, rag-vector-searchcontainerized-unverifiedneed a datastore / vector index
core/python/long-horizon-harness, ambient-expense-agentcontainerized-unverified + already-deployable flagthey already serve; see the advisory below
contrib/python/market-research-agent, core/python/deep-search, core/python/safety-pluginsblockedadk-locked-version — locked on ADK 1.x
core/python/cross-session-memory, genmedia-for-commerce, oauth-user-consent-flowblockedadk-version-floor — the ceiling excludes the floor
contrib/python/cross-border-data-routerblockedlegacy app_utils

The already-deployable advisory. When a recipe already has a Dockerfile and a <pkg>/fast_api_app.py, it serves by its own arrangement. long-horizon-harness is the case: a bespoke ~400-line entrypoint wiring A2A from its own horizon/a2a/ package. Neither file is replaced without --overwrite, but app_utils/ modules generated alongside a bespoke entrypoint are dead code unless someone wires them in. Confirm the owner wants to migrate onto the standard layout before applying.

© google, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

SKILL.md and 8 other files (scripts) in .agents/skills/make-python-recipe-deployable of google/adk-recipes.

  • SKILL.md
  • resources/templates/Dockerfile
  • resources/templates/app_utils/a2a.py
  • resources/templates/app_utils/reasoning_engine_adapter.py
  • resources/templates/app_utils/services.py
  • resources/templates/fast_api_app.py
  • scripts/make_deployable.py
  • tests/conftest.py
  • tests/test_make_deployable.py

Open the folder on GitHubat commit c339821

Compare with similar skills

Make Python Recipe Deployable next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Make Python Recipe Deployable compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Make Python Recipe Deployable this skillgoogle/adk-recipes10k—~6.9kAutomated safety check: NotesApache-2.0
Devops Deploysickn33/agentic-awesome-skills47k2 repos~1.9kAutomated safety check: PassMIT
Sca TrivyAgentSecOps/SecOpsAgentKit2202 repos~3.7kAutomated safety check: PassCustom licence
Security Analyzeraiskillstore/marketplace430—~1.2kAutomated safety check: NotesNone
Senior DevOps Toolkitmaslennikov-ig/claude-code-orchestrator-kit2606 repos~1.1kAutomated safety check: NotesCustom licence
Verifylkmeta/txtify135—~583Automated safety check: PassApache-2.0

Similar skills

  • Devops Deploy

    sickn33/agentic-awesome-skills

    DevOps e deploy de aplicacoes — Docker, CI/CD com GitHub Actions, AWS Lambda, SAM, Terraform, infraestrutura como codigo e monitoramento.

    47k GitHub starsUsed in 2 repos~1.9k tokens
    DevOps & CloudAuto-check passed
  • Sca Trivy

    AgentSecOps/SecOpsAgentKit

    Software Composition Analysis (SCA) and container vulnerability scanning using Aqua Trivy for identifying CVE vulnerabilities in dependencies, container images, IaC misconfigurations, and license…

    220 GitHub starsUsed in 2 repos~3.7k tokens
    SecurityAuto-check passed
  • Security Analyzer

    aiskillstore/marketplace

    Comprehensive security vulnerability analysis for codebases and infrastructure.

    430 GitHub stars~1.2k tokensUpdated yesterday
    SecurityAuto-check: notes
  • Senior DevOps Toolkit

    maslennikov-ig/claude-code-orchestrator-kit

    Comprehensive DevOps skill for CI/CD, infrastructure automation, containerization, and cloud platforms (AWS, GCP, Azure). Includes pipeline setup…

    260 GitHub starsUsed in 6 repos~1.1k tokens
    DevOps & CloudAuto-check: notes
  • Verify

    lkmeta/txtify

    Verify a Txtify change end-to-end. An agent skill from lkmeta/txtify.

    135 GitHub stars~583 tokensUpdated 1 mo ago
    DevOps & CloudAuto-check passed
  • Docker

    EliasOulkadi/shokunin

    Optimize Docker images with multi-stage builds, distroless bases, BuildKit cache mounts, multi-arch builds, compose watch, security hardening (non-root, seccomp, capabilities drop), and…

    114 GitHub stars~3.8k tokensUpdated 3 days ago
    DevOps & CloudAuto-check: notes

More from google/adk-recipes

All 14 skills in this repo
  • Retail Product Search Agent

    google/adk-recipes

    Official

    Builds a retail product search agent on Google Cloud, from catalog ingestion into BigQuery and Vector Search to ADK scaffolding, evaluation and Cloud Run deployment.

    10k GitHub stars~3k tokensUpdated today
    Auto-check passed
  • Align Recipe pyproject.toml

    google/adk-recipes

    Official

    Brings a Python recipe's pyproject.toml in line with the repo's CI rules, either as a read-only dry run or by rewriting the file while keeping comments.

    10k GitHub stars~4.6k tokensUpdated today
    Auto-check passed
  • Official

    Generates a minimal tests/test_runnability.py for a Python agent recipe that imports the agent module and checks root_agent, adding only the mocks and env vars it needs.

    10k GitHub stars~3.3k tokensUpdated today
    Auto-check passed
  • Retail Virtual Try-On Agent

    google/adk-recipes

    Official

    Sets up a virtual try-on agent on Google Cloud that generates image and catwalk-video try-ons with Gemini, from first setup through local testing.

    10k GitHub stars~3.5k tokensUpdated today
    Auto-check passed
  • Scaffold Python ADK Recipe

    google/adk-recipes

    Official

    Creates a new Python recipe for the ADK recipes repository by running a scaffold script that copies template files, after confirming the output directory and recipe name.

    10k GitHub stars~931 tokensUpdated today
    Auto-check passed
  • Official

    Reviews a GitHub pull request and drafts a small set of inline comments in a human reviewing voice, each checkable from the line it points at, then posts them after approval.

    10k GitHub stars~8.4k tokensUpdated today
    Auto-check passed

Categories

Questions about Make Python Recipe Deployable

What does Make Python Recipe Deployable do?

Makes an existing Python recipe deployable: generates the serving files a container needs (Dockerfile, .dockerignore, fastapiapp.py, apputils/a2a.py, apputils/services.py…. Make Python Recipe Deployable is an agent skill from google/adk-recipes, published by the product's own GitHub organization.deployable).

When should I use Make Python Recipe Deployable?

Make Python Recipe Deployable fits situations like: the user wants to make this recipe deployable; add a Dockerfile to a recipe; add the serving files; containerize a recipe.

How do I install Make Python Recipe Deployable in Claude Code?

Run `npx skills add google/adk-recipes --skill make-python-recipe-deployable -a claude-code`. Or copy the skill folder (.agents/skills/make-python-recipe-deployable in google/adk-recipes) into .claude/skills/make-python-recipe-deployable in your project. Claude Code loads it when a task matches its description.

How do I install Make Python Recipe Deployable in Codex?

Run `npx skills add google/adk-recipes --skill make-python-recipe-deployable -a codex`. Or copy the skill folder (.agents/skills/make-python-recipe-deployable in google/adk-recipes) into .agents/skills/make-python-recipe-deployable in your project. Codex loads it when a task matches its description.

Can I use Make Python Recipe Deployable in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add google/adk-recipes --skill make-python-recipe-deployable -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/make-python-recipe-deployable, .gemini/skills/make-python-recipe-deployable, .github/skills/make-python-recipe-deployable and .opencode/skills/make-python-recipe-deployable in your project.

What does Make Python Recipe Deployable need to run?

Going by SKILL.md and its folder, Make Python Recipe Deployable needs Python for the scripts in its folder and the command-line tools its instructions call (uv and python3). Our summary lists: Python 3; Docker.

Does Make Python Recipe Deployable access the network?

SKILL.md contains no URLs. Its commands use uv, which can reach the network depending on how they are called. This is read from the text; nothing was executed.

Is Make Python Recipe Deployable safe to install?

Our automated static check of SKILL.md found notes only (mentions a .env file), nothing it rates as a warning. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.

What licence does Make Python Recipe Deployable use?

Make Python Recipe Deployable is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Make Python Recipe Deployable use?

About 6.9k tokens (SKILL.md is roughly 28k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Make Python Recipe Deployable?

Skills that share tags, products or a category with Make Python Recipe Deployable: Devops Deploy (sickn33/agentic-awesome-skills, 47k stars), Sca Trivy (AgentSecOps/SecOpsAgentKit, 220 stars), Security Analyzer (aiskillstore/marketplace, 430 stars) and Senior DevOps Toolkit (maslennikov-ig/claude-code-orchestrator-kit, 260 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Make Python Recipe Deployable?

google (a GitHub organization, an official publisher) maintains it in google/adk-recipes, which has 10,421 GitHub stars. The repository holds 14 skills in this directory. The repository was last updated on October 8, 2026.

Source: google/adk-recipes on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.