> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentscope.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Environment Awareness

> Keep the agent aware of time, tasks, and context usage as they change

An agent stays aware of its changing environment through **runtime state injection**: before each reasoning step, information that changes across turns (current time, plan tasks, context usage) is injected into the context as a `HintBlock`, configured via the `injection_config` parameter of `Agent(...)`.

The injection covers three dimensions, each with its own timing rule:

| Dimension     | Injected Content                                                                | When It Is Injected                                                                                                                                                             |
| ------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Time          | The current wall-clock time and its timezone                                    | No time is recorded in the context (the first reply, or right after a context compression), or the elapsed time since the recorded one exceeds `time_interval` hours            |
| Plan tasks    | The counts of in-progress and pending tasks, with a reminder to call `TaskList` | Uncompleted tasks exist while the context contains neither task-related tool calls (e.g. compressed away) nor a previous tasks injection                                        |
| Context usage | The current input tokens and the compression threshold                          | At the first iteration of a reply, when the input tokens come within `context_buffer_ratio` of the compression threshold, letting the agent perceive that a compression is near |

## How Injection Works

Each injected field is wrapped as `<key>value</key>`, and all fields are joined and placed into the `template` (a `<system-reminder>` wrapper by default). A typical injected hint looks like:

```text Example Injected Hint theme={null}
<system-reminder>Treat the following as the ground truth at this point of the conversation. Anything stated earlier is outdated, and a later reminder, if any, supersedes this one:
<current-time>2026-07-22T10:30:00</current-time>
<timezone>Asia/Shanghai</timezone>
<tasks>You have 1 in-progress tasks and 2 pending tasks. Use `TaskList` to view them if you don't know.</tasks>
</system-reminder>
```

Three design decisions are worth knowing:

* The injection is **not ephemeral**: it is appended to the persistent context on purpose, so the agent can perceive how time elapses and what it did at each step, building a sense of time.
* The hint is attached as a `HintBlock` instead of mutating the system prompt, so prompt caching still works while the agent stays aware of the changing state.
* Only information that **changes** within a conversation is injected. Fixed information (the agent's identity, standing instructions) belongs in the system prompt.

When an injection happens and `emit_hint_event` is enabled, `reply_stream` also yields a `HintBlockEvent`, so a frontend can render the injected hint.

## Configure Injection

Pass an `InjectionConfig` to the agent constructor to tune the injection behavior:

```python theme={null}
from agentscope.agent import Agent, InjectionConfig
from agentscope.model import DashScopeChatModel
from agentscope.credential import DashScopeCredential

agent = Agent(
    name="my_agent",
    system_prompt="You are a helpful assistant.",
    model=DashScopeChatModel(
        credential=DashScopeCredential(api_key="YOUR_API_KEY"),
        model="qwen-max",
    ),
    injection_config=InjectionConfig(
        timezone="Asia/Shanghai",  # inject the time of this timezone
        time_interval=1.0,         # refresh the time at most once per hour
    ),
)
```

The fields of `InjectionConfig`:

| Field                  | Default                                            | Description                                                                                                                                                                      |
| ---------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `inject_runtime_state` | `True`                                             | Master switch; set `False` to disable runtime state injection entirely                                                                                                           |
| `timezone`             | `"UTC"`                                            | Timezone of the injected time, in the standard timezone database format (e.g. `"Asia/Shanghai"`)                                                                                 |
| `time_format`          | `"%Y-%m-%dT%H:%M:%S"`                              | Format of the injected time; must carry the date part so the recorded time round-trips as a full timestamp                                                                       |
| `time_interval`        | `0.5`                                              | Minimum elapsed time in hours from the recorded time to trigger a new time injection                                                                                             |
| `context_buffer_ratio` | `0.2`                                              | Buffer ahead of the compression threshold; with a trigger ratio of 0.8 and a buffer of 0.2, context usage is injected once the input tokens exceed 60% of the model context size |
| `template`             | A `<system-reminder>` wrapper                      | Template around the injected fields; must contain the `{runtime_state}` placeholder                                                                                              |
| `injection_source`     | `{"label": "System", "sublabel": "Runtime State"}` | The `source` of the injected `HintBlock`, used to recognize the agent's own previous injections when scanning the context                                                        |
| `task_tool_names`      | `TaskCreate`, `TaskGet`, `TaskList`, `TaskUpdate`  | Tool names whose calls in the context indicate the agent is already aware of the tasks, suppressing the tasks injection                                                          |
| `extra_fields`         | `{}`                                               | Custom fields attached to every injection (see [Inject Custom Fields](#inject-custom-fields))                                                                                    |
| `emit_hint_event`      | `True`                                             | Whether to emit a `HintBlockEvent` when an injection happens                                                                                                                     |

<Note>
  `context_buffer_ratio` must be smaller than the `trigger_ratio` of the [context config](/versions/2.0.5dev/en/building-blocks/context/compress-context#configure-compression), so that the context usage is injected before the compression happens. Otherwise the agent constructor raises a `ValueError`.
</Note>

## Inject Custom Fields

Beyond the built-in dimensions, `extra_fields` injects developer-defined information, such as sensor readings or deployment metadata:

```python theme={null}
from agentscope.agent import InjectionConfig

injection_config = InjectionConfig(
    extra_fields={
        "battery-level": "78%",       # injected as <battery-level>78%</battery-level>
        "location": "Hangzhou office",
    },
)
```

Extra fields are attached to **every** injection but never trigger one by themselves: they ride along whenever the time, tasks, or context dimension fires.

## Customize the Template

The `template` field controls how the injected fields are presented to the LLM. It must contain the `{runtime_state}` placeholder, which is replaced by the joined `<key>value</key>` fields:

```python theme={null}
from agentscope.agent import InjectionConfig

injection_config = InjectionConfig(
    template=(
        "[Runtime update] The following reflects the current environment:\n"
        "{runtime_state}"
    ),
)
```
