How does Google ADK skill lifecycle actually work?
AI Architect
Key takeaways
- Google ADK ships skill lifecycle control as an experimental feature gated by `ADK_ENABLE_SKILL_LIFECYCLE=1`.
- Google ADK applies `max_active_skills` only to `bounded` skills and evicts the least recently loaded bounded skill first.
- Google ADK keeps an `ephemeral` skill active for every model step in one invocation and then releases it on the next turn.
- Google ADK treats an `ephemeral` skill as stream-long under `run_live`, because that surface has no turn boundary to expire on.
- Google ADK can invalidate prompt-cache reuse when a skill adds tools or when `revalidate_skills=True` re-states a changed skill.
Google ADK’s new skill lifecycle is more specific than the release headline.
The core finding is in skill_toolset.py: max_active_skills only applies to
BOUNDED skills, while PERSISTENT and EPHEMERAL are both exempt. If you
expected the cap to control every loaded skill, the source says otherwise.
That matters for teams using skills to keep a growing agent prompt under control. Google ADK already frames skills as progressive disclosure, the same economy behind prompt caching: keep expensive instructions out of the prefix until they earn their place. Lifecycle mode is the second half of that design, because it decides when the skill stops earning that place.
What did Google ADK skill lifecycle add in v2.10.0?
Google ADK v2.10.0 added three lifecycle modes for SkillToolset under an
experimental flag, ADK_ENABLE_SKILL_LIFECYCLE=1: PERSISTENT, BOUNDED and
EPHEMERAL. The release notes describe this as skill lifecycle modes plus an
active-skill cap, and the skills guide adds a sixth tool, unload_skill, when
the lifecycle feature is enabled. The mechanism is narrower than the headline.
The code defines lifecycle on a per-skill basis through
SkillLifecycleConfig, with a default mode, per-skill overrides, a
max_active_skills value and optional revalidate_skills.
The useful change is that skill lifetime becomes explicit state rather than an accident of session length. Before this, a loaded skill stayed active for the rest of the session unless the model never reached for it again. After v2.10.0, the toolset can keep a skill for the whole session, keep it only while it remains one of the most recently loaded bounded skills, or keep it for one invocation only. That is a real control surface for agents with many specialist skills.
Which Google ADK skills count against max_active_skills?
Only BOUNDED skills count against max_active_skills. The enum docstring in
skill_toolset.py states that PERSISTENT skills neither count against the cap
nor get evicted by it, and EPHEMERAL skills are “bounded by time” so the cap
ignores them as well. The eviction code matches the docstring: it builds a list
of active bounded skills, calculates overflow against the configured cap, then
drops the oldest bounded entries first. Reloading a bounded skill moves it to
the end, which makes the eviction policy least recently loaded, with reload
counting as fresh use.
That makes the cap a queue manager for one mode. A team can still accumulate
many active skills if it marks them PERSISTENT, and it can still keep a high
churn of short-lived skills if it marks them EPHEMERAL. For engineering teams
already weighing
Google ADK against LangGraph, this is an important
distinction: ADK’s lifecycle control is concrete and useful, but it is not a
blanket context-budget governor.
Which Google ADK lifecycle modes count toward the cap?
Show data
| Item | Value (counts toward max_active_skills) | Note |
|---|---|---|
| Persistent | 0 | never evicted by the cap |
| Bounded | 1 | the only mode the cap governs |
| Ephemeral | 0 | expires by turn instead |
When does a Google ADK ephemeral skill actually expire?
An EPHEMERAL skill lasts for one invocation, which ADK treats as one turn. The
source stores the invocation id that loaded the skill and considers the skill
expired when a later invocation asks for the active set. The docstring is clear
that this includes every model step and tool call caused by the same user turn,
so ephemeral does not mean one tool call or one model response. It means the
whole cascade of work kicked off by the turn that loaded it.
The sharp edge is run_live. ADK documents that a live bidi stream has no turn
boundary, so an ephemeral skill behaves as persistent until the stream ends.
That is an easy failure mode if a team reads “ephemeral” as “brief” without
checking the surface. On a request-response agent, ephemeral is a clean way to
load a narrow skill, use it through a few tool calls, and then let it disappear.
On a long voice or streaming session, the same choice can keep the skill active
far longer than intended.
How one Google ADK ephemeral skill lives and expires
Show as text
| # | From | To | Message |
|---|---|---|---|
| 1 | Agent invocation | SkillToolset | load_skill(skill_name). lifecycle set to ephemeral |
| 2 | SkillToolset | Agent invocation | skill and extra tools become active |
| 3 | Agent invocation | SkillToolset | later model steps and tool calls in the same invocation |
| 4 | SkillToolset | Agent invocation | skill still active for this turn |
| 5 | Agent invocation | SkillToolset | next user turn starts |
| 6 | SkillToolset | Agent invocation | skill is absent until loaded again. unless the surface is run_live |
How do Google ADK skills affect prompt caching and revalidation?
The skills guide draws a useful line between loading instructions and changing
the tool surface. A normal load_skill call sends the skill body back as a tool
response, so the system prompt prefix stays stable. That keeps the cache story
cleaner than many teams expect. The bigger cache risk comes from
metadata.adk_additional_tools, because a skill that activates extra tools
changes the declared tool list on the next request, and ADK’s docs say that
breaks a context-cache hit. A second cache risk comes from
revalidate_skills=True, which compares active skills against their current
definition every request and re-states any changed skill.
That trade is reasonable for registry-backed catalogs that change mid-session.
The skill registry guide says fetched skills are cached inside SkillToolset,
but a session can still outlive a skill revision. Revalidation fixes that drift
at the cost of a registry lookup per active skill per turn, plus a cache miss
when the skill body is re-stated. Teams that care about both skill freshness and
latency need to budget for both.
Which Google ADK skill features disturb prompt-cache reuse?
Show data
| Item | Value (cache-hit risk) | Note |
|---|---|---|
| Load instructions only | 0 | tool response leaves the prefix stable |
| Add tools by metadata | 1 | tool declarations change next turn |
| Re-state a changed skill | 1 | refreshed instructions change the prefix |
Which Google ADK skill lifecycle mode should a production agent use?
My view is simple. Default task-specific skills to EPHEMERAL on normal
request-response agents, reserve PERSISTENT for tiny skills whose
instructions remain useful across most of the session, and use BOUNDED for
skills a user is likely to revisit across several nearby turns. That policy
matches the mechanism ADK actually ships rather than the broader impression a
“max active skills” headline can create.
The production question is the same one that appears in
agent read and write controls: what stays in
scope long enough to change behaviour on later turns? A persistent skill keeps
its instructions and extra tools around. A bounded skill keeps them until newer
bounded skills push it out. An ephemeral skill narrows the blast radius to one
invocation, except on run_live, where the blast radius is the whole stream.
Choose the mode by that future impact first, then tune the cap. The cap is
secondary because it governs only one of the three modes.
Do this
Roll out Google ADK skill lifecycle without surprising your agent
Treat lifecycle selection as prompt and tool budgeting, because that is what the feature actually controls.
Enable the experimental feature deliberately
Turn on `ADK_ENABLE_SKILL_LIFECYCLE=1` only in environments where an experimental ADK surface is acceptable, then pin the ADK version that you tested.
Classify each skill by how long its instructions should matter
Put task-shaped skills in `ephemeral`, reusable conversation skills in `bounded`, and only very small evergreen skills in `persistent`.
Set `max_active_skills` after choosing modes
The cap governs bounded skills only, so choose the number after you know which skills will count against it and which ones will bypass it.
Audit every skill that uses `metadata.adk_additional_tools`
Those extra tools change the declared tool list on the next request, which can drop a prompt-cache hit even when the skill instructions themselves were loaded cheaply.
Keep `revalidate_skills` for catalogs that change during live sessions
A stable local skill folder does not need a registry lookup per active skill per turn. Dynamic shared catalogs sometimes do.
Avoid `ephemeral` for long `run_live` streams
ADK documents that `run_live` has no turn boundary, so an ephemeral skill there behaves like a stream-long persistent skill until the stream ends.
Frequently asked questions
- Does `max_active_skills` limit every active Google ADK skill?
- No. The source says only `bounded` skills count against the cap. `persistent` skills and `ephemeral` skills stay outside that count.
- Can a Google ADK ephemeral skill survive several tool calls?
- Yes. It stays active for the whole invocation that loaded it, which includes later model steps and tool calls in the same turn.
- What happens when Google ADK unloads a skill?
- The skill's tools stop being available and later requests replace the earlier `load_skill` instruction payload with a short unloaded notice. The stored session events still keep the original response.
- Should `revalidate_skills=True` be on by default?
- Usually no. It adds a registry lookup per active skill per turn and can invalidate prompt-cache reuse when a changed skill is re-stated.
Sources
Revision history
- : First publication.
- : First published.