wenjin272 opened a new issue, #1085:
URL: https://github.com/apache/flink-agents/issues/1085

   ### Search before asking
   
   - [x] I searched in the 
[issues](https://github.com/apache/flink-agents/issues) and found nothing 
similar.
   
   ### Description
   
   This is a child issue of #1055. Cross-language Action execution was 
introduced under #622; this issue reviews the usability of its public 
declaration API.
   
   #### Current API
   
   A Java Agent can dispatch an Action to Python by attaching a nested 
`PythonFunction` annotation to an annotated Java method:
   
   ```java
   @Action(
           value = EventType.InputEvent,
           target =
                   @PythonFunction(
                           module = "my_pkg.handlers",
                           qualname = "handle_input"))
   public static void handle(Event event, RunnerContext ctx) {
       throw new UnsupportedOperationException("cross-language stub");
   }
   ```
   
   The annotated Java method is not executed. It serves only as the declaration 
anchor and supplies the Action name, while the Python function is the actual 
executable target.
   
   The Python decorator API has a similar form when dispatching to Java: a 
decorated Python function is required even though its body is only a 
placeholder.
   
   #### Problems
   
   - `@Action` has two different meanings: for native Actions the annotated 
method is the implementation, while for cross-language Actions the method must 
never be invoked.
   - Users must write a valid-looking method/function whose only purpose is to 
fail if called directly.
   - The placeholder signature does not validate the real cross-language 
target. In particular, the Java plan-layer `PythonFunction.checkSignature()` is 
a no-op, so target signature errors are still discovered by the Python runtime.
   - Java exposes two different public types named `PythonFunction`: 
`api.annotation.PythonFunction` and the data descriptor 
`api.function.PythonFunction`. Both carry `module` and `qualname`, but cannot 
be reused interchangeably.
   - Action identity is split between the placeholder member name and the 
target function's qualified name, which makes declarations and diagnostics 
harder to understand.
   - Annotation/decorator-based registration and programmatic 
`addAction`/`add_action` registration provide overlapping ways to create the 
same plan, but have different shapes and capabilities.
   
   #### Design goals
   
   - Preserve annotation-based Action declarations as a first-class API style.
   - Make the annotated element represent the actual Action implementation or 
executable descriptor.
   - Avoid requiring a throwing or no-op placeholder body for cross-language 
Actions.
   - Keep native and cross-language Action declarations easy to distinguish and 
explain.
   - Reuse a single function-descriptor model where practical.
   - Keep Java, Python, and YAML semantically aligned around Action name, 
trigger conditions, executable function, and configuration.
   - Validate malformed declarations and unresolved/incompatible targets as 
early as the relevant runtime boundary permits.
   
   #### Proposal for discussion: annotate a function-descriptor field
   
   > [!IMPORTANT]
   > The following is only a proposal for discussion, not an accepted API 
decision. This issue is intended to compare annotation-based alternatives and 
agree on the public API before implementation.
   
   One possible design is to allow `@Action` on both methods and fields:
   
   ```java
   public class MyAgent extends Agent {
   
       // The annotated method is the native Java implementation.
       @Action(EventType.InputEvent)
       public static void processLocally(Event event, RunnerContext ctx) {
           // Java Action implementation
       }
   
       // The annotated field contains the actual cross-language target 
descriptor.
       @Action(EventType.InputEvent)
       private static final PythonFunction handle =
               PythonFunction.of("my_pkg.handlers", "handle_input");
   }
   ```
   
   Under this proposal:
   
   - `@Action` on a method requires a static Java Action with the `(Event, 
RunnerContext)` signature and produces a `JavaFunction` descriptor.
   - `@Action` on a field requires a static final field whose value is an 
API-layer `Function` descriptor.
   - The method or field name is the default Action name; an optional 
annotation attribute could override it if needed.
   - Invalid member kinds, null descriptors, duplicate Action names, and 
invalid native signatures fail during plan construction.
   - The existing API-layer `PythonFunction` data descriptor is reused, so a 
separate nested annotation type with the same name is unnecessary.
   
   Other annotation-preserving designs should also be evaluated, for example a 
repeatable class-level annotation or a dedicated cross-language Action 
annotation. The final choice should be based on the design goals above rather 
than assumed by this proposal.
   
   #### Scope
   
   - Review the Java `@Action(target = @PythonFunction(...))` API and the 
corresponding Python decorator form.
   - Define the intended relationship between annotation/decorator 
declarations, function descriptors, and programmatic Action registration.
   - Agree on an annotation-preserving declaration model for cross-language 
Actions.
   - Define plan-construction and runtime validation behavior.
   - Update Java/Python plan compilation, serialization snapshots, 
cross-language runtime tests, examples, and documentation after the design is 
agreed.
   
   Compatibility and migration mechanics are outside the scope of this issue.
   
   #### Acceptance criteria
   
   - Annotation-based Action declaration remains supported and documented as a 
first-class style.
   - A cross-language Action does not require an unused method/function body 
that throws or does nothing.
   - Native annotated methods continue to clearly represent executable native 
implementations.
   - Cross-language target descriptors have one unambiguous public 
representation per language.
   - Action name, trigger conditions, target, and validation behavior are 
semantically aligned across Java, Python, and YAML.
   - Invalid declarations fail with actionable errors before processing user 
records where possible.
   - Plan serialization and Java-to-Python/Python-to-Java integration tests 
cover the agreed design.
   - The final API decision and rationale are recorded in this issue before 
implementation.
   
   ### Are you willing to submit a PR?
   
   - [x] I'm willing to submit a PR!
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to