Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions docs/src/modules/sdk/partials/compile-time-validations-agent.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
== Compile-time validations

The Akka Java SDK validates Agent components at compile time to catch configuration errors early.

include::compile-time-validations-common.adoc[tag=intro]

=== Agent-specific validations

In addition to the xref:compile-time-validations-common.adoc[common validations], Agents have the following specific requirements:

==== Single command handler

An Agent must have exactly one public method returning either `Agent.Effect` or `Agent.StreamEffect`. This is the main entry point for the agent.

==== Agent metadata

Use `@Component` (with `name` and `description` parameters) and `@AgentRole` to specify agent metadata:

* `@Component.name` - the display name of the agent
* `@Component.description` - a description of what the agent does
* `@AgentRole` - the role of the agent (e.g., "assistant", "helper")

==== @FunctionTool restrictions for agents

Unlike other components, Agents have special rules for `@FunctionTool`:

* Command handlers (methods returning `Agent.Effect` or `Agent.StreamEffect`) cannot be annotated with `@FunctionTool`
* Helper methods can be annotated with `@FunctionTool` to expose them as tools for the agent
* Private methods _can_ be annotated with `@FunctionTool` (this is unique to Agents)

==== Command handler arity

Check failure on line 31 in docs/src/modules/sdk/partials/compile-time-validations-agent.adoc

View workflow job for this annotation

GitHub Actions / Vale style checking

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'arity'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'arity'?", "location": {"path": "docs/src/modules/sdk/partials/compile-time-validations-agent.adoc", "range": {"start": {"line": 31, "column": 22}}}, "severity": "ERROR"}

Agent command handlers follow the common rule: they must have zero or one parameter.

=== Why these validations matter

These validations ensure:

* **Clear agent interface**: A single entry point makes the agent's purpose unambiguous
* **Proper tool definition**: Only helper methods can be tools, not the main command handler
* **Consistent metadata**: Agent descriptions come from one source, preventing conflicts
* **Simplified implementation**: Catching these issues at compile time saves debugging time
51 changes: 51 additions & 0 deletions docs/src/modules/sdk/partials/compile-time-validations-common.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
== Compile-time validations

The Akka Java SDK uses annotation processors to validate your component configuration at compile time. This catches common errors early in the development cycle, before you even run your application.

=== Common validations

The following validations apply to all component types:

==== Component must be public

Components must be declared with the `public` modifier.

==== Valid component ID

Every component must have a unique identifier specified via the `@Component` annotation's `id` parameter.

The component ID must:

* Not be empty or blank
* Not contain the pipe character `|`

==== At least one effect method

Each component must have at least one public method returning the appropriate Effect type for that component (e.g., `KeyValueEntity.Effect`, `Workflow.Effect`, etc.).

==== Command handler arity

Check failure on line 26 in docs/src/modules/sdk/partials/compile-time-validations-common.adoc

View workflow job for this annotation

GitHub Actions / Vale style checking

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'arity'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'arity'?", "location": {"path": "docs/src/modules/sdk/partials/compile-time-validations-common.adoc", "range": {"start": {"line": 26, "column": 22}}}, "severity": "ERROR"}

Command handler methods (public methods returning an Effect type) can only accept zero or one parameter. If you need to pass multiple arguments, wrap them in a class.

==== @FunctionTool restrictions

The `@FunctionTool` annotation is used to expose methods as tools for AI agents. However, it has specific restrictions:

* Cannot be used on private methods (except in Agent components where tools can be private)
* Can only be used on specific method types depending on the component (see component-specific validations)

=== Validation system architecture

The compile-time validation system consists of:

* **ComponentValidationProcessor**: A Java annotation processor that runs during compilation
* **Component-specific validation classes**: Each component type has its own validation logic

When you compile your code, the annotation processor:

1. Discovers all classes annotated with `@Component`
2. Runs component-specific validations
3. Reports any errors through the Java compiler
4. Fails the build if validation errors are found

This ensures that configuration errors are caught immediately during development, rather than at runtime or deployment time.
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
== Compile-time validations

The Akka Java SDK validates Consumer components at compile time to catch configuration errors early.

include::compile-time-validations-common.adoc[tag=intro]

=== Consumer-specific validations

In addition to the xref:compile-time-validations-common.adoc[common validations], Consumers have the following specific requirements:

==== Must have @Consume annotation

A Consumer must be annotated with one of the `@Consume` subscription annotations to specify its data source.

==== Single type-level subscription

A Consumer can only have one type-level `@Consume` annotation. You cannot combine multiple subscription sources.

Available type-level subscription annotations:

* `@Consume.FromKeyValueEntity`
* `@Consume.FromWorkflow`
* `@Consume.FromEventSourcedEntity`
* `@Consume.FromServiceStream`
* `@Consume.FromTopic`

==== Topic publishing requires source

If you use `@Produce.ToTopic` to publish to a topic, the Consumer must also have a `@Consume` source annotation.

==== Service stream ID required

When producing to a service stream, the stream ID cannot be empty.

==== Subscription method parameter count

Subscription methods (methods that handle incoming data) must have exactly one parameter, unless they are marked with `@DeleteHandler`.

==== No ACL on subscription methods

Consumer subscription methods are for internal use only and cannot have ACL annotations like `@Acl.Allow` or `@Acl.Deny`.

==== State subscription validations

When consuming from KeyValueEntity or Workflow state changes, special rules apply:

===== Delete handlers must have zero parameters

Methods annotated with `@DeleteHandler` must not have parameters.

===== Only one update method allowed

You cannot have multiple methods handling the same state type for state subscriptions.

===== Only one delete handler allowed

Only one method can be annotated with `@DeleteHandler` per Consumer.

==== Ambiguous handler validation

When subscribing to event sources, you cannot have multiple handlers that accept the same parameter type.

==== Missing handler validation

When subscribing to event sources with sealed event types, you must provide handlers for all event types.

You can satisfy this requirement in one of three ways:

1. **Provide specific handlers** for each permitted subclass of the sealed interface
2. **Provide a handler** for the sealed interface itself (handles all events)
3. **Provide a raw `byte[]` handler** (handles all events as raw bytes)

For KeyValueEntity and Workflow subscriptions, you must have a handler for the state type and/or a delete handler.

==== @FunctionTool restrictions

Consumer methods cannot have `@FunctionTool` on private methods. Only public methods returning `Consumer.Effect` can be annotated with `@FunctionTool`, if applicable to the use case.

=== Why these validations matter

These validations ensure:

* **Correct subscription setup**: Every Consumer has a valid data source
* **Complete event handling**: All event types are handled, preventing runtime errors
* **Type safety**: Handler signatures match the expected data types
* **Security**: Internal subscription methods cannot be exposed via ACLs
* **Unambiguous routing**: Each event type maps to exactly one handler
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
== Compile-time validations

The Akka Java SDK validates EventSourcedEntity components at compile time to catch configuration errors early.

include::compile-time-validations-common.adoc[tag=intro]

=== EventSourcedEntity-specific validations

In addition to the xref:compile-time-validations-common.adoc[common validations], EventSourcedEntities have the following specific requirements:

==== Unique command handler names

EventSourcedEntity command handlers must have unique names. Method overloading is not supported for command handlers.

==== Event type must be sealed

The event type parameter of an EventSourcedEntity must be a sealed interface. This ensures that all possible event types are known at compile time and can be properly validated.

NOTE: This validation ensures type safety and completeness when consuming events from the entity, as Consumers need to know all possible event types.

==== @FunctionTool only on Effect methods

The `@FunctionTool` annotation can only be used on methods that return `EventSourcedEntity.Effect` or `EventSourcedEntity.ReadOnlyEffect`. It cannot be used on other methods or private methods.

==== Command handler arity

Check failure on line 25 in docs/src/modules/sdk/partials/compile-time-validations-eventsourcedentity.adoc

View workflow job for this annotation

GitHub Actions / Vale style checking

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'arity'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'arity'?", "location": {"path": "docs/src/modules/sdk/partials/compile-time-validations-eventsourcedentity.adoc", "range": {"start": {"line": 25, "column": 22}}}, "severity": "ERROR"}

Command handlers (methods returning `Effect` or `ReadOnlyEffect`) must have zero or one parameter.

=== Event sourcing best practices

These validations support event sourcing best practices:

* **Sealed event types** ensure complete event handling and type safety
* **Unique command names** prevent ambiguous routing and make the API clear
* **Limited parameters** encourage thoughtful command design
* **Effect-based tools** ensure AI agents can only interact through the proper effect system

=== Why these validations matter

These validations ensure:

* **Type safety**: All event types are known and validated at compile time
* **Clear API**: Unique command names prevent confusion and routing errors
* **Proper tool exposure**: Only command handlers can be exposed as tools for AI agents
* **Event sourcing correctness**: Sealed types guarantee complete event handling in consumers
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
== Compile-time validations

The Akka Java SDK validates KeyValueEntity components at compile time to catch configuration errors early.

include::compile-time-validations-common.adoc[tag=intro]

=== KeyValueEntity-specific validations

In addition to the xref:compile-time-validations-common.adoc[common validations], KeyValueEntities have the following specific requirements:

==== Unique command handler names

KeyValueEntity command handlers must have unique names. Method overloading is not supported for command handlers.

==== @FunctionTool only on Effect methods

The `@FunctionTool` annotation can only be used on methods that return `KeyValueEntity.Effect` or `KeyValueEntity.ReadOnlyEffect`. It cannot be used on other methods or private methods.

==== Command handler arity

Check failure on line 19 in docs/src/modules/sdk/partials/compile-time-validations-keyvalueentity.adoc

View workflow job for this annotation

GitHub Actions / Vale style checking

[vale] reported by reviewdog 🐶 [Vale.Spelling] Did you really mean 'arity'? Raw Output: {"message": "[Vale.Spelling] Did you really mean 'arity'?", "location": {"path": "docs/src/modules/sdk/partials/compile-time-validations-keyvalueentity.adoc", "range": {"start": {"line": 19, "column": 22}}}, "severity": "ERROR"}

Command handlers (methods returning `Effect` or `ReadOnlyEffect`) must have zero or one parameter.

=== Key-value entity patterns

KeyValueEntity is designed for simpler state management compared to EventSourcedEntity:

* **Direct state updates**: No event sourcing, just update the state directly
* **No sealed type requirements**: State can be any serializable type
* **Read and write separation**: Use `Effect` for writes, `ReadOnlyEffect` for reads

=== Why these validations matter

These validations ensure:

* **Clear API**: Unique command names prevent confusion and routing errors
* **Proper tool exposure**: Only command handlers can be exposed as tools for AI agents
* **Simple command design**: Limited parameters encourage thoughtful API design
* **Type safety**: Compile-time checks prevent runtime errors
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
== Compile-time validations

The Akka Java SDK validates TimedAction components at compile time to catch configuration errors early.

include::compile-time-validations-common.adoc[tag=intro]

=== TimedAction-specific validations

In addition to the xref:compile-time-validations-common.adoc[common validations], TimedActions have the following specific requirements:

==== No @FunctionTool allowed

TimedAction methods cannot be annotated with `@FunctionTool`. TimedActions are designed to be triggered by timers, not called as tools by AI agents. This includes both public and private methods.

==== Command handler arity

Command handler methods (methods returning `TimedAction.Effect`) must have zero or one parameter.

=== TimedAction design patterns

TimedActions are designed for scheduled and delayed operations:

* **Timer-based execution**: Triggered by timers, not direct invocations
* **No tool exposure**: Cannot be called as tools by AI agents
* **Async patterns**: Often used for scheduled cleanup, batch processing, or delayed notifications

Common use cases:

* Scheduled cleanup tasks
* Periodic batch processing
* Delayed notifications
* Timeout handlers
* Recurring maintenance tasks

=== Why these validations matter

These validations ensure:

* **Proper component usage**: TimedActions are for scheduled execution, not interactive tools
* **Clear separation of concerns**: Prevents confusion between scheduled tasks and callable operations
* **Simple action design**: Limited parameters encourage focused, single-purpose actions
Loading
Loading