4949import io .reactivex .rxjava3 .core .Flowable ;
5050import io .reactivex .rxjava3 .core .FlowableEmitter ;
5151import java .util .ArrayList ;
52+ import java .util .LinkedHashMap ;
5253import java .util .List ;
54+ import java .util .Map ;
5355import java .util .Objects ;
5456import java .util .Optional ;
5557import java .util .function .BiConsumer ;
@@ -84,6 +86,7 @@ public class RemoteA2AAgent extends BaseAgent {
8486 private final Client a2aClient ;
8587 private String description ;
8688 private final boolean streaming ;
89+ private final @ Nullable A2ARequestMetadataProvider requestMetadataProvider ;
8790
8891 // Internal constructor used by builder
8992 private RemoteA2AAgent (Builder builder ) {
@@ -117,6 +120,7 @@ private RemoteA2AAgent(Builder builder) {
117120 this .description = this .agentCard .description ();
118121 }
119122 this .streaming = builder .streaming && this .agentCard .capabilities ().streaming ();
123+ this .requestMetadataProvider = builder .requestMetadataProvider ;
120124 }
121125
122126 public static Builder builder () {
@@ -133,6 +137,7 @@ public static class Builder {
133137 private List <Callbacks .BeforeAgentCallback > beforeAgentCallback ;
134138 private List <Callbacks .AfterAgentCallback > afterAgentCallback ;
135139 private boolean streaming ;
140+ private @ Nullable A2ARequestMetadataProvider requestMetadataProvider ;
136141
137142 @ CanIgnoreReturnValue
138143 public Builder streaming (boolean streaming ) {
@@ -182,6 +187,16 @@ public Builder a2aClient(Client a2aClient) {
182187 return this ;
183188 }
184189
190+ /**
191+ * Sets an optional provider called once for each outgoing message, after its parts and
192+ * identifiers have been populated. Session state is never forwarded automatically.
193+ */
194+ @ CanIgnoreReturnValue
195+ public Builder requestMetadataProvider (@ Nullable A2ARequestMetadataProvider provider ) {
196+ this .requestMetadataProvider = provider ;
197+ return this ;
198+ }
199+
185200 public RemoteA2AAgent build () {
186201 return new RemoteA2AAgent (this );
187202 }
@@ -198,19 +213,30 @@ private Message.Builder newA2AMessage(
198213
199214 private Message prepareMessage (InvocationContext invocationContext ) {
200215 Event userCall = EventConverter .findUserFunctionCall (invocationContext .session ().events ());
216+ Message message ;
201217 if (userCall != null ) {
202218 ImmutableList <io .a2a .spec .Part <?>> parts =
203219 EventConverter .contentToParts (userCall .content (), userCall .partial ().orElse (false ));
204- return newA2AMessage (invocationContext , Message .Role .USER , parts )
205- .taskId (EventConverter .taskId (userCall ))
206- .contextId (EventConverter .contextId (userCall ))
207- .build ();
220+ message =
221+ newA2AMessage (invocationContext , Message .Role .USER , parts )
222+ .taskId (EventConverter .taskId (userCall ))
223+ .contextId (EventConverter .contextId (userCall ))
224+ .build ();
225+ } else {
226+ message =
227+ newA2AMessage (
228+ invocationContext ,
229+ Message .Role .USER ,
230+ EventConverter .messagePartsFromContext (invocationContext ))
231+ .build ();
232+ }
233+ if (requestMetadataProvider == null ) {
234+ return message ;
208235 }
209- return newA2AMessage (
210- invocationContext ,
211- Message .Role .USER ,
212- EventConverter .messagePartsFromContext (invocationContext ))
213- .build ();
236+ Map <String , Object > metadata = requestMetadataProvider .provide (invocationContext , message );
237+ return metadata == null
238+ ? message
239+ : new Message .Builder (message ).metadata (new LinkedHashMap <>(metadata )).build ();
214240 }
215241
216242 @ Override
0 commit comments