credo-ts icon indicating copy to clipboard operation
credo-ts copied to clipboard

Add option to hold inbound transport sessions for longer than processing the message

Open TimoGlastra opened this issue 4 years ago • 3 comments

When building an agent that interacts with other agents that don't have an endpoint (lets say you're a mediator), you can communicate with the other agent by using the inbound transport as a return route.

When we have auto accept for mediation requests enabled, and also auto accept for connections enabled this works pretty well. The response is created when we receive the message (e.g. we send the mediate-grant directly as response to the mediate-request).

However when auto accept is not enabled and the external controller would like to decide whether to respond to an incoming message it is not possible to respond. The other agent has an endpoint of didcomm:transport/queue which makes it impossible to send a message.

We should look at adding an option to delay the termination of the inbound route, so it gives time to create a response to the incoming message. Another option is to require autoAcceptConnection and autoAcceptMediationRequests to be enabled when interacting with agents without an inbound transport.

I recently interacted with a discord JS library that managed this pretty nicely I think, which we can maybe us as inspiration. Whenever a command is invoked you have 3 seconds to respond to the incoming message, if you want to reply you should invoke a deferReply method which gives you 15 minutes to respond. If deferReply is not called, you can't reply anymore directly

Maybe we can look at something like the following:

  1. If a response is created and sent over the channel which also closes it (http can only give 1 response), the channel is already closed. Nothing we can do here.
  2. If no response is created we emit an event with the session attached. You can listen to these events, and call a method on the session to delay the closing.
  3. If the session hasn't been kept open it will automatically be closed after X seconds. If it has, it will be closed once used, or X amount of time has passed.

It can be quite hard to know whether you want to keep a session alive. For example for mediation requests you would need to monitor all mediation requests, find the associated connection id and also find associated sessions with that same connection id. Therefore it may be useful to add an option that, if enabled, detects whether the other agent has an endpoint of didcomm:transport/queue and if so, it will keep the connection alive for longer. This allows the user to still just use the normal grantMediation call, but internally it kept on to the session, because it knows this is the only way to reply to the incoming message.

I think the websocket transport already keeps session open, but in the HTTP inbound transport we have the following statement after processing a message:

        // If agent did not use session when processing message we need to send response here.
        if (!res.headersSent) {
          res.status(200).end()
        }

TimoGlastra avatar Mar 11 '22 11:03 TimoGlastra

@TimoGlastra -- it seems to me that this would be an issue for ACA-Py as well. Correct? Should we be doing the same thing?

swcurran avatar Mar 14 '22 13:03 swcurran

Yes this is also an issue in ACA-Py, had to enable auto-accept as well to be able to interact with agents without an endpoint

TimoGlastra avatar Mar 14 '22 15:03 TimoGlastra

However when auto accept is not enabled and the external controller would like to decide whether to respond to an incoming message it is not possible to respond. The other agent has an endpoint of didcomm:transport/queue which makes it impossible to send a message.

We should look at adding an option to delay the termination of the inbound route, so it gives time to create a response to the incoming message. Another option is to require autoAcceptConnection and autoAcceptMediationRequests to be enabled when interacting with agents without an inbound transport.

I don't think it is strictly needed to require both autoAcceptConnection and autoAcceptMediationRequests enabled, as it is possible to queue responses to InMemoryMessageRepository and then the client can retrieve it by polling (e.g. using explicit pick-up messaging). Currently, this flow using AFJ for both mediator/mediatee roles works in WebSocket (as you said, the session is not closed) and HTTP. But in the latter it is needed to do a pickup loop on the client until mediation is granted (e.g. something like await agent.mediationRecipient.pickupMessages(mediatorConnection)).

That said, there is certainly room to improve a lot this use case, as currently there are no guarantees regarding the time the sessions would be valid (and the message queue will be stored).

genaris avatar Mar 14 '22 16:03 genaris