You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@flink.apache.org by "addu390 (via GitHub)" <gi...@apache.org> on 2026/05/21 13:53:50 UTC

[D] [Feature] Cross Language Actions [flink-agents]

GitHub user addu390 created a discussion: [Feature] Cross Language Actions

## Context
After #631 (event refactor) and #670 (Function descriptors), the runtime and plan layers already do most of the heavy lifting needed for cross-language actions. #622 covers what's left: pinning down the usage patterns and closing other gaps in SerDe, E2E Tests, Examples and Documentation.


## What's already there
`JavaFunction` and `PythonFunction` data descriptors in both languages. `add_action(func=Function)` / `addAction(Function)` accept cross-language descriptors, and `ActionExecutionOperator` dispatches by `instanceof JavaFunction` vs `PythonFunction`. The YAML loader can already express cross-language actions via `type: java|python` + `function: class:method`.

So today, cross-language usage would look like:


```python
class MyAgent(Agent):
    def __init__(self):
        super().__init__()
        self.add_action(
            name="handle",
            events=["my_event"],
            func=JavaFunction(
                qualname="com.example.Handlers",
                method_name="handle",
                parameter_types=["org.apache.flink.agents.api.Event",
                                 "org.apache.flink.agents.api.context.RunnerContext"],
            ),
        )
```

## What's missing
Three gaps:
- **Decorator parity.** `@action` / `@Action` can't declare a foreign target today, only the imperative `add_action` can.
- **SerDe inconsistencies.** Either to fix the inconsistencies, or clearly call out the lack of support, backed by comprehensive cross-language tests on built-in events.
- **E2E test coverage for cross-language actions.** Nothing currently exercises a user-authored Java action consuming an event from a user-authored Python action (or vice versa). Built-in event SerDe is only partially exercised today through the resource path and needs comprehensive coverage to surface issues across all built-in events.

## Standardizing the usage pattern
The imperative form already exists, the question is should we and what the `decorator` form looks like. Two options worth noting down:

Option A, descriptor object:

```python
@action(events=["my_event"], target=JavaFunction(
    qualname="com.example.Handlers",
    method_name="handle",
    parameter_types=[...],
))
def handle(): ... 
```

Option B, string form (a bit out of convention in the code-base):

```python
@action(events=["my_event"], target="java:com.example.Handlers#handle")
def handle(): ...
```

Java would mirror whichever shape we pick. Option A, although verbose would be more consistent with existing usage.

## SerDe standardization

Cross-language actions work regardless of event payload format, but events also need to be cross-language-safe for the feature to be usable end-to-end. Once events cross the language boundary they go through JSON SerDe, and any built-in event whose Jackson form doesn't line up with its Pydantic form breaks the consumer.

Categories of mismatch worth checking are enum casing, field naming convention (camelCase vs snake_case), and optional/null handling.
The fix is to pick one wire format, `snake_case` fields, lowercase enum values, and annotate the Java side (`@JsonValue` on a lowercase accessor, or `@JsonProperty` per constant) to conform. Python is already in that shape.

So, two paths forward, not mutually exclusive:

- Audit the built-in events (`ChatRequestEvent`, `ChatResponseEvent`, `ToolRequestEvent`, etc.) and align both sides on the same wire format.
- For anything we choose not to support cross-language, document it explicitly and add tests that pin the boundary.

Either way, the gate is comprehensive cross-language tests on built-in events so this stops being a discovery problem.

## Signature validation

Same-language signature validation already works (`JavaFunction.checkSignature` in Java, `PythonFunction.check_signature` in Python). The cross-language sides are empty stubs right now and worth filling those gaps for the full cross language support.
- Java's `PythonFunction.checkSignature`, no validation that the Python function takes `(Event, RunnerContext)`.
- Python's `JavaFunction.check_signature`, no validation that the Java method signature matches the declared `parameter_types`.

## Tests
For each built-in event, two directions: Java-emit / Python-consume and Python-emit / Java-consume. This is the matrix that would have caught the kind of SerDe mismatches discussed above, and is also what signature-validation regression tests sit on top of.

## Open questions
- Preferred decorator shape, descriptor object or string or any other?
- Anything else worth surfacing before implementation starts?

GitHub link: https://github.com/apache/flink-agents/discussions/697

----
This is an automatically sent email for issues@flink.apache.org.
To unsubscribe, please send an email to: issues-unsubscribe@flink.apache.org


Re: [D] [Feature] Cross Language Actions [flink-agents]

Posted by "wzhero1 (via GitHub)" <gi...@apache.org>.
GitHub user wzhero1 added a comment to the discussion: [Feature] Cross Language Actions

Hi @addu390, wenjin272 is on vacation, so I'll take a look.

Overall direction looks good — I think this is ready to start. All three gaps (decorator parity, SerDe, E2E tests) are correctly identified and the proposed approach is reasonable. A few details on each gap below.

---

## Gap 1 — Decorator parity details

**Leaning Option A**: it aligns with the existing imperative form `add_action(func=JavaFunction(...))`, and `parameter_types` stays a structured field. Option B's string form can't carry `parameter_types`; squeezing them in would just turn the string into a mini-DSL.

Two follow-ups for landing it:

### 1. Python `@action` backward compat

The snippet `@action(events=["my_event"], target=...)` doesn't actually work against today's signature `def action(*listen_events: str)` — Python varargs don't accept `events=` as a keyword, so existing `@action("foo")` usage would break. Suggest keeping varargs and adding a keyword-only `target` for zero breakage:

```python
def action(*listen_events: str, *, target: Function | None = None) -> Callable: ...
```

### 2. Stub body convention

The `def handle(): ...` body decorated with `@action(target=...)` never runs — that's a new wrinkle the decorator form introduces (the imperative `add_action` doesn't have it since there's no method). Suggest the body be `raise NotImplementedError("cross-language stub")` so direct calls outside the framework (unit tests, debugging) fail loud rather than silently passing. `pass` / `...` as a fallback.

---

## Gap 2 — SerDe inconsistencies details

### Pin down audit scope

The full set of built-in events in the repo is 8: InputEvent / OutputEvent / ChatRequest / ChatResponse / ToolRequest / ToolResponse / ContextRetrievalRequest / ContextRetrievalResponse. Suggest classifying each:

- **Must support in 0.3**: at least ChatRequest / ChatResponse (chat model main path)
- **OK to defer past 0.3**: probably ToolResponseEvent — both an attr-set divergence and a Map-type divergence (see below); not solvable by simple SerDe tweaks. Document the gap explicitly and add a boundary test pinning the "doesn't work cross-language" state to prevent regression

### Wire format spec

The design's 3 categories (snake_case fields, lowercase enum values, optional/null handling) cover **naming-level** divergences (e.g. `MessageRole` "USER" vs "user", `ChatMessage.toolCalls` vs `tool_calls`).

Suggest adding two more rules to cover schema-level divergences:

- **Attribute sets aligned on both sides** — e.g. `ToolResponseEvent` Java has `success` / `error` / `timestamp` (`ToolResponseEvent.java:46-49`) that Python doesn't (`tool_event.py:96-103`).
- **No `Object` / `Any` fallback; `Map<K, V>` must have matching K and V types** — e.g. `responses` is `Map<String, ToolResponse>` on Java vs `Dict[UUID, Any]` on Python; `ChatRequestEvent.outputSchema` Java uses `Object` (`ChatRequestEvent.java:42`).

---

## Gap 3 — E2E test coverage details

### Test scope = the "must support" list from Gap 2

Test matrix should share the same event list as Gap 2's "must support" tier. Events Gap 2 defers (e.g. ToolResponseEvent) get a boundary test pinning the unsupported state instead of e2e.

### Add a user-authored event axis

Built-in events alone aren't enough — user-authored events dominate cross-language action scenarios. Two cases:

- `Event(type="my_custom", attributes={...primitive...})` — both sides use base `Event`
- User defines `class MyEvent(Event)` in Python with no Java counterpart — test Java-side fallback (base `Event` reception) degrades gracefully

### Form: round-trip + JSON snapshot

Beyond round-trip e2e, also add **JSON snapshot tests** — pin a fixed wire-format JSON string and have both sides deserialize, then assert typed access. Snapshot turns Gap 2's wire format spec into an **executable contract**: spec changes → snapshot changes → CI enforces both sides stay in sync.


GitHub link: https://github.com/apache/flink-agents/discussions/697#discussioncomment-17050163

----
This is an automatically sent email for issues@flink.apache.org.
To unsubscribe, please send an email to: issues-unsubscribe@flink.apache.org


Re: [D] [Feature] Cross Language Actions [flink-agents]

Posted by "addu390 (via GitHub)" <gi...@apache.org>.
GitHub user addu390 added a comment to the discussion: [Feature] Cross Language Actions

@wzhero1 Thanks for the added context, on the same page. While going over the implementation today, realized the biggest gap are the tests, so, I'd expect that to be the majority of the PR. I did raise an early draft: https://github.com/apache/flink-agents/pull/709, not in draft mode right now to check for the CI runs.

GitHub link: https://github.com/apache/flink-agents/discussions/697#discussioncomment-17079870

----
This is an automatically sent email for issues@flink.apache.org.
To unsubscribe, please send an email to: issues-unsubscribe@flink.apache.org


Re: [D] [Feature] Cross Language Actions [flink-agents]

Posted by "addu390 (via GitHub)" <gi...@apache.org>.
GitHub user addu390 edited a comment on the discussion: [Feature] Cross Language Actions

@wzhero1 Thanks for the added context, on the same page. While going over the implementation today, realized the biggest gap are the tests, so, I'd expect that to be the majority of the PR. I did raise an early PR: https://github.com/apache/flink-agents/pull/709

GitHub link: https://github.com/apache/flink-agents/discussions/697#discussioncomment-17079870

----
This is an automatically sent email for issues@flink.apache.org.
To unsubscribe, please send an email to: issues-unsubscribe@flink.apache.org