Events & Schemas

Learn how AgentML treats LLM outputs as structured events validated against JSON schemas.

Events and Schema Validation

AgentML treats LLM outputs as events. When the agent is in a state that expects certain events, it will prompt the LLM accordingly. The LLM's response must be a JSON object that the runtime interprets as an event. To enforce correctness, AgentML uses JSON Schema validation on these events.

How Schema Validation Works

1. Declare Schema on Transitions

You declare an event:schema on transitions to define the expected structure and content of the event. This schema can enforce types, required fields, specific values, etc.

2. LLM Output Validation

When the LLM produces output, the AgentML interpreter will parse it and validate it against the schema. If it fails validation (or doesn't correspond to any expected event), the event can be rejected or handled as an error.

3. Guide with Descriptions

By providing detailed description fields in the schema (both at the top level and for each property), you guide the LLM to produce the correct data. These descriptions act like the spec that the LLM tries to fulfill.

Why Use Schemas?

This approach shifts the prompt paradigm from "LLM as free-text oracle" to "LLM as function that must return a specific JSON shape." It dramatically improves reliability.

  • You can be confident that when a transition fires, the data is present and well-formed
  • Schemas serve as up-to-date documentation of what the agent expects at each step
  • Schema definitions can be reviewed and version-controlled like code
  • Reduces debugging time by catching malformed outputs early

Example: Flight Search Intent

<transition event="intent.flight.search"
            event:schema='{
              "type": "object",
              "description": "User intent to search for a flight",
              "properties": {
                "category": {
                  "const": "flight",
                  "description": "Category identifier for flight requests"
                },
                "action": {
                  "const": "search",
                  "description": "Specific action is flight search"
                },
                "details": {
                  "type": "object",
                  "properties": {
                    "from": {
                      "type": "string",
                      "description": "Departure location"
                    },
                    "to": {
                      "type": "string",
                      "description": "Destination location"
                    }
                  }
                }
              },
              "required": ["category", "action"]
            }'
            target="handle_flight_search"/>

In this snippet, any LLM output event must have category: "flight" and action: "search", plus optional details like from/to. The LLM will see in the prompt that an event with name intent.flight.search is expected and what fields it should include.

Best Practices

Use Specific Event Names

Prefer granular events like intent.flight.search or user.profile.update over generic names. Specific names make the flow clear and avoid unintended catches.

Leverage JSON Pointer References

Instead of embedding large schemas inline, load them via use:events="events.json" and reference with events:#/components/schemas/YourEvent. This keeps your agent file clean and promotes reuse.

Use const and enum for Fixed Values

When an event field should only ever be a specific value (like a category flag), use a JSON Schema const to enforce it. For a set of allowed values, use an enum with clear descriptions.

Next Steps

Learn how AgentML optimizes token usage through runtime snapshots and caching.

Token Efficiency →