An AI agent uses a large language model to plan and orchestrate actions toward a goal. Unlike a system that only retrieves data and answers questions, it can inspect external state, call tools in sequence, check results, and adjust its plan. Unlike fixed-rule automation, it can break a high-level objective into changing subtasks. section 8.4.2 section 1.2.5
In a digital twin, the agent needs contextualized data about the physical system and access to appropriate APIs, data stores, or control systems. Its decisions are only as reliable as that data foundation. section 8.0 section 8.4.2
A practical agent separates the goal from the means of acting:
- Tools expose specific functions, such as querying an inverter, a weather forecast, or a digital twin API. Document their inputs and outputs so the agent can select and use them. section 8.4.3
- An agent loop manages reasoning, tool execution, and context across multiple steps rather than treating each model response as the finished task. section 8.4.3
- A control policy bounds action: permit low-risk adjustments, require approval for consequential decisions, and withhold unauthorized safety-critical actions. section 1.2.5
Solar-aware climate control
A home agent reads solar production, indoor conditions, and the weather forecast to decide whether excess solar energy can support cooling. It can change the HVAC temperature setpoint—for example, precooling before cloud cover increases—while the deterministic HVAC controller operates the equipment. The distinction matters: the agent chooses a strategy, not a direct compressor command. section 8.4.3 section 8.4.4
Listing 8.10 Tool to query Fronius Symo inverter power data
from strands import tool
@tool #1
def get_realtime_solar_data(scope: str = "System") -> Dict[str, Any]:
""" #2
Fetches real-time solar production metrics from the local Fronius
inverter.
Use this tool when you need to know the current solar output (PAC) or
the total energy produced today (DAY_ENERGY).
Args:
scope: The data scope to query. Defaults to "System".
Returns:
Dict[str, Any]: A dictionary containing:
- current_power_w: Current AC power output in Watts.
- day_energy_wh: Total energy produced today in Watt-hours.
- timestamp: The time of the reading.
"""
url = "http://192.168.1.180/solar_api/v1/GetInverterRealtimeData.cgi" #3
try:
response = requests.get(url, params={"Scope": scope}, timeout=5)
response.raise_for_status()
data = response.json()
realtime_data = data.get("Body", {}).get("Data", {})
pac_value = realtime_data.get("PAC", {}).get("Values", {}).
get("1", 0)
day_energy = realtime_data.get("DAY_ENERGY", {}).get("Values",
{}).get("1", 0)
return {
"current_power_w": pac_value,
"day_energy_wh": day_energy,
"timestamp": data.get("Head", {}).get("Timestamp"),
"status": "success",
}
except requests.RequestException as e:
return {
"status": "error",
"message": f"Failed to connect to inverter: {str(e)}",
}
The inverter-query function illustrates a narrowly scoped tool: a Python function decorated with `@tool` and documented with the readings it returns. section 8.4.3
Listing 8.11 Agent with Strands SDK for home climate control
import datetime
from strands import Agent
current_time_str = datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ")
system_prompt = f""" #1
### ROLE
Climate Control Agent. Current Time: {current_time_str}.
### CONSTANTS
- **Target Temp:** 21°C–24°C
- **AC Load:** 1500W
- **Baseload:** 1000W (08:00–16:00); 200W (otherwise).
### CONTROL POLICY
1. **Fetch Data:** Get current solar ($P_{{solar}}$), forecast,
and indoor temp ($T_{{room}}$ (last 24 hours).
2. **Calculate Excess:** $P_{{excess}} = P_{{solar}} - \\text{{Baseload}}$.
3. **Evaluate State:**
- **COOLING NEEDED** if $T_{{room}} > 24°C$.
- **OPPORTUNISTIC COOLING** if $P_{{excess}} > 1500W$ AND $T_{{room}} >
21°C$ (Priority: Solar).
- **IDLE** otherwise.
4. **Safety:** Apply hysteresis (don't cycle AC if state changed
<15 mins ago).
5. **Priorities:** Always prioritize minimizing grid consumption
over comfort.
### OUTPUT INSTRUCTION
Output a concise reasoning step (e.g., "Excess solar 1600W > AC Load;
engaging cooling."), then call `set_aircon_state` if a change is needed.
"""
agent = Agent( #2
name="ClimateAgent",
system_prompt=system_prompt,
tools=[
get_realtime_solar_data,
get_weather_forecast,
get_space_climate_history,
set_aircon_state,
],
)
The climate-control listing shows how an agent prompt expresses targets, operating priorities, and a safety rule against rapid AC cycling. section 8.4.3
Do not substitute an agent for a dependable controller merely because it can reason across more variables. LLM decisions can vary or be wrong; supervisory control keeps physical regulation with deterministic systems. For broader duties, specialized agents with limited tools can reduce conflicting goals and mistaken tool selection. Model decision frequency and token costs before deployment: frequent calls can cost more than the savings they produce. section 8.4.4 section 8.4.5 section 8.5.3
































