Skip to content

Commit 597fac3

Browse files
haranrkcopybara-github
authored andcommitted
docs(agents): add system-instruction sample and guide section
Add a runnable sample under contributing/samples/managed_agent/system_instruction demonstrating the new ManagedAgent.instruction field, and document the field in the ManagedAgent guide. Co-authored-by: Haran Rajkumar <haranrk@google.com> PiperOrigin-RevId: 951709300
1 parent f1a0a14 commit 597fac3

4 files changed

Lines changed: 170 additions & 0 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
# Managed Agent — System Instruction
2+
3+
> For setup, authentication, backends, and background on `ManagedAgent`, see the
4+
> [ManagedAgent guide](../../../../docs/guides/agents/managed_agent/index.md).
5+
6+
## Overview
7+
8+
This sample runs a `ManagedAgent` whose behavior is shaped by its `instruction`
9+
field. `instruction` is forwarded to the Managed Agents API as the interaction's
10+
system instruction (the same role `LlmAgent.instruction` plays for a local
11+
model). Here it pins a persona and output format, so its effect is visible in
12+
every reply.
13+
14+
`instruction` accepts either a plain string (which may embed `{state_var}`
15+
placeholders resolved from session state) or an `InstructionProvider` callable.
16+
This sample uses an **`InstructionProvider`**: `persona_instruction` takes a
17+
`ReadonlyContext`, reads the reply language from `state['response_language']`
18+
(defaulting to English), and returns the instruction string. Because a provider
19+
is invoked on every turn, the instruction is rebuilt each turn from the current
20+
state; unlike a string, it bypasses `{placeholder}` injection, so you build the
21+
final text yourself. A provider may also be `async` (return an awaitable `str`).
22+
23+
## Sample Inputs
24+
25+
- `What is the capital of France?`
26+
27+
The reply obeys the instruction: a single terse sentence ending with a
28+
relevant emoji, in the language from `state['response_language']` (English by
29+
default).
30+
31+
- `And Japan?`
32+
33+
A follow-up turn that reuses the recovered remote sandbox and previous
34+
interaction. The provider runs again on this turn, demonstrating that the
35+
system instruction is resolved and sent on chained turns too — and would pick
36+
up any change to `response_language` in session state.
37+
38+
## Graph
39+
40+
```mermaid
41+
graph LR
42+
User -->|message| ManagedAgent
43+
ManagedAgent -->|interactions.create + system_instruction| ManagedAgentsAPI
44+
ManagedAgentsAPI -->|streamed events| ManagedAgent
45+
ManagedAgent -->|reply shaped by the instruction| User
46+
```
47+
48+
## How To
49+
50+
- **Set the instruction**: pass `instruction=...` to `ManagedAgent`. A string is
51+
sent as-is (after `{placeholder}` resolution); an `InstructionProvider`
52+
callable is invoked per turn and bypasses placeholder injection.
53+
- **Use an `InstructionProvider`**: define a callable that takes a
54+
`ReadonlyContext` and returns a `str` (or an awaitable `str`), then pass it as
55+
`instruction`. Read `readonly_context.state` to build the instruction
56+
dynamically — here `state['response_language']` selects the reply language.
57+
- **Observe the effect**: every reply follows the persona/format the instruction
58+
specifies, on the first turn and on chained follow-up turns.
59+
- **Drive it**: a `ManagedAgent` is a `BaseAgent`, so a standard `Runner` runs it
60+
just like any other agent.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from . import agent
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Copyright 2026 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""A ManagedAgent with an ``InstructionProvider`` system instruction.
16+
17+
``ManagedAgent.instruction`` is forwarded to the Managed Agents API as the
18+
interaction's system instruction, the same way ``LlmAgent.instruction`` shapes a
19+
local model. It accepts either a plain string (which may embed ``{state_var}``
20+
placeholders resolved from session state) or an ``InstructionProvider`` — a
21+
callable invoked with a ``ReadonlyContext`` that returns the instruction string
22+
and bypasses placeholder injection.
23+
24+
This sample uses an ``InstructionProvider`` so the instruction is built
25+
dynamically, per turn, from session state: it pins a terse persona and reads the
26+
reply language from ``state['response_language']`` (defaulting to English). The
27+
persona keeps the effect visible in every reply, and because the provider runs
28+
on every turn the instruction adapts if the state changes on a later turn.
29+
30+
Run with ``adk web`` / ``adk run
31+
contributing/samples/managed_agent/system_instruction``. See the README for the
32+
required environment / auth setup.
33+
"""
34+
35+
import os
36+
37+
from google.adk.agents import ManagedAgent
38+
from google.adk.agents.readonly_context import ReadonlyContext
39+
40+
# The Managed Agent id served by the Managed Agents API. Override with the
41+
# MANAGED_AGENT_ID environment variable if your project has access to a
42+
# different agent.
43+
_DEFAULT_AGENT_ID = 'antigravity-preview-05-2026'
44+
45+
46+
def persona_instruction(readonly_context: ReadonlyContext) -> str:
47+
"""Builds the system instruction dynamically from session state.
48+
49+
An ``InstructionProvider`` is any callable that takes a ``ReadonlyContext``
50+
and returns the instruction (a ``str``, or an awaitable ``str`` for async
51+
providers). It is invoked on every turn, so the instruction can adapt to the
52+
current session state, and — unlike a plain string — it bypasses
53+
``{placeholder}`` injection, leaving you to build the final string yourself.
54+
"""
55+
language = readonly_context.state.get('response_language', 'English')
56+
return (
57+
'You are a terse assistant. Always answer in a single sentence, in'
58+
f' {language}, and end every reply with a relevant emoji.'
59+
)
60+
61+
62+
root_agent = ManagedAgent(
63+
name='managed_persona_agent',
64+
agent_id=os.environ.get('MANAGED_AGENT_ID', _DEFAULT_AGENT_ID),
65+
# Provision a remote sandbox; the environment id is recovered from prior
66+
# events so follow-up turns reuse the same sandbox.
67+
environment={'type': 'remote'},
68+
# Pass an InstructionProvider callable instead of a plain string: it is
69+
# invoked per turn with a ReadonlyContext and returns the resolved
70+
# instruction that is forwarded as the interaction's system_instruction.
71+
instruction=persona_instruction,
72+
)

docs/guides/agents/managed_agent/index.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ Response text appears in both places (the local ADK events and the remote
125125
interaction history), but ADK stores only the ids it needs to recover and reuse
126126
the remote state; it never re-sends prior turns.
127127

128+
### System instruction
129+
130+
Set `instruction` on `ManagedAgent` to send a system instruction to the Managed
131+
Agents API, mirroring `LlmAgent.instruction`. It accepts a plain string — which
132+
may embed `{state_var}` / `{artifact.name}` / `{var?}` placeholders resolved
133+
from session state and artifacts at request time — or an `InstructionProvider`
134+
callable that is invoked with a `ReadonlyContext` and bypasses placeholder
135+
injection. The resolved instruction is forwarded as the interaction's
136+
`system_instruction` on every turn, including chained turns; an empty
137+
`instruction` (the default) sends none.
138+
139+
```python
140+
from google.adk.agents import ManagedAgent
141+
142+
root_agent = ManagedAgent(
143+
name='managed_persona_agent',
144+
agent_id='antigravity-preview-05-2026',
145+
environment={'type': 'remote'},
146+
instruction='You are a terse assistant. Answer in a single sentence.',
147+
)
148+
```
149+
128150
## Advanced applications
129151

130152
### Tool encapsulation for orchestration
@@ -154,3 +176,4 @@ the remote state; it never re-sends prior turns.
154176

155177
* [Managed Agent Basic](../../../../contributing/samples/managed_agent/basic)
156178
* [Managed Agent Code Execution](../../../../contributing/samples/managed_agent/code_execution)
179+
* [Managed Agent System Instruction](../../../../contributing/samples/managed_agent/system_instruction)

0 commit comments

Comments
 (0)