Step 1: construction

The constructor of your LlmAgent subclass runs. No I/O should happen here — keep it cheap, fields only.

public class WeatherAgent extends LlmAgent {
  private final String apiEndpoint;  // set here
  public WeatherAgent(String endpoint) {
    this.apiEndpoint = endpoint;
  }
}
Advertisement

Step 2: onStart

onStart(AgentContext ctx) is where I/O belongs — credential fetch, cache warm, connection pool init. If this throws, the agent never accepts traffic. That's the point.

@Override
protected void onStart(AgentContext ctx) {
  this.apiKey = SecretsClient.get("WEATHER_KEY");
  this.httpClient = HttpClient.newBuilder()
      .connectTimeout(Duration.ofSeconds(5))
      .build();
}
Advertisement

Step 3: instruction compilation

The runtime compiles the instruction returned by getInstruction() into a runtime-friendly form. If you use template variables (e.g. {user_name}), this is when they get validated.