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]
