Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

potential RFC, not ready to merge: 0547 Invite Action Protocol #550

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 135 additions & 0 deletions features/0547-invite-action-protocol/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Aries RFC 0547: Invite Action Protocol

- Authors: [Daniel Hardman]([email protected])
- Status: [PROPOSED](/README.md#proposed)
- Since: 2020-09-30
- Status Note: newly submitted for community consideration, based on a use case developed by the credit union industry in the United States. Implements a concept first called "please play a role" that was discussed on community calls in mid 2020 in conjunction with the [Out of Band protocol](../0434-outofband/README.md).
- Start Date: 2020-09-30
- Tags: [feature](/tags.md#feature), [protocol](/tags.md#protocol)
- URI: https://didcomm.org/invite-action/%VER

## Summary

Provides a mechanism for one [agent](../../concepts/0004-agents/README.md) to invite another to take a particular action. The action is described in a way that can be automated. It may be accompanied by supporting data. The invited agent may or may not trust the inviter, and may choose to react in various ways -- ignore the invitation, accept it, defer a decision, etc.

## Motivation

DIDComm protocols often make a strong assumption about who is the "first mover" -- the role that must emit the protocol's initial message. For example, in [RFC 0193: Coin Flip Protocol](../0193-coin-flip/README.md), the `recorder` always begins by saying, in essence, "Let's flip a coin. I'll toss and you call." There is no option to say, "Let's flip a coin. You toss and I'll call." The `recorder` role always starts.

Human interactions are more flexible: when we want someone else to take the first step, we can simply ask them to do so: "We should do lunch sometime. Why don't you send me an appointment?"

In the DIDComm ecosystem, we want automated, software-driven interactions to have the potential for this same flexibility. Suppose Alice is a recruiter who identifies Bob as a match for a job she's trying to fill. If an `apply-for-job` protocol says the `applicant` must make the first move, how can Alice invite Bob to start the interaction? Certainly, she can have a flexible human conversation. But what if Alice is managing thousands of job openings and prospective applicants, and she wants to use her agent to get work done at scale, driven by automation and policy? And what if Bob wants to sort such invitations into "spam" and "worth reading" buckets using automated policies of his own? How can agents achieve the same flexiblity without depending on humans?

One answer is to modify each protocol to allow multiple parties to initiate. This strategy is used in [RFC 0036: Issue Credential Protocol](../0036-issue-credential/README.md), for example, where either the `issuer` can offer or the prospective `holder` can request. It could be used to modify an `apply-for-job` protocol so recruiters can reach out to applicants.

Sometimes this answer may be appropriate. However, one issue with it as a general strategy is that it requires extra logic built into every protocol handler, even though the inversion of normal ordering is pretty formulaic. In other words, it creates lots of boilerplate rather than a reusable, composable mechanism.

Another issue is that we also want agents to be able to suggest actions to one another that may not be DIDComm protocols at all. Alice is driving beside a car that appears to have a flat; she wants to suggest to the car (if it's self-driving) or to the driver (if it's a more traditional vehicle) that it might be a good idea to inspect the tire. Either way, this will involve sending a message to some sort of agent, inviting an "inspect the tire" action. But inspecting tires is not a protocol to which Alice is party; it may not be a protocol at all. Alice doesn't care; she just wants to suggest the action.

#### Existing Mechanisms

The community has addressed subsets of these use cases in other ways. Comparing Invite Action to these other mechanism may make the motivation of this new RFC clearer:

mechanism | what's alike, what's different
----------|-----------------
Basic Message Protocol | Lets humans invite one another to take arbitrary actions, but requires human intelligence for decision-making. Arbitrary attachments — available in all DIDComm contexts — can carry machine-actionable payloads, but the history of email demonstrates that it's unsafe to trigger machine actions based on attachments without predefined semantics. Also, the mime type of an attachment does not necessarily indicate which action is desired (is an attached PDF supposed to be saved, printed, displayed to the user...). And there's no useful way to separate messages intended for human interpretation from messages that automation should handle.
Out of Band Protocol (RFC 434) | Like Invite Action, OOB lets the sender propose to the receiver that the receiver take an action — and automation can be built on the receiving side, because the action is described with a formal goal code. However, OOB is for situations where no channel is known to exist between two parties, and it always involves transmitting a message over a non-DIDComm channel. OOB assumes that either a handshake protocol or `~request-attach` is relevant; it doesn't allow a goal code to be sent in isolation. Only Invite Action supports actions that are not protocols in the DIDComm sense.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OOB [...] always involves transmitting a message over a non-DIDComm channel

note: OOB messages can be forwarded through DIDComm channels with the introduce protocol (aries-framework-go already does this).

Co-protocol Protocol (RFC 0482) | Allows an agent to trigger or attach to a subactivity or side activity of some sort. However, it assumes that this other activity is a DIDComm protocol, and that the two agents that participate have a relationship of trust. Invite Action does not assume trust between agents, and does not assume that the party doing the inviting has a stake in ongoing communication about the action.
Action Menu (RFC 0509) | Allows one agent to trigger an action in another. However, this requires a round trip; the requester asks for a menu from the responder, and then selects an item to be performed. If Action Menu were revised to support goal codes and if it supported a short-circuit whereby there didn't need to be a round trip, and if Action Menu supported the advanced form of `~please_ack`, these protocols might be collapsible

## Tutorial

### Name and Version

The official name of the protocol is "Invite Action"; its official version is 0.9. This is reflected in its [PIURI](../../concepts/0003-protocols/README.md#piuri):

>`https://didcomm.org/invite-action/0.9`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a question: why 0.9 and not 1.0 like every other protocol?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll update to 1.0 after it's socialized with the community a little bit. There are a couple parts of this protocol that I don't feel confident about yet.


### Key Concepts

This protocol approximates the flow of a classic two-message request-response protocol, except that two responses are possible rather than one, and both responses are optional.

### Roles

The protocol has two roles: `inviter` and `invitee`.

### States

The `inviter` sends a message inviting the `invitee` to take an action. The message may include an advanced [`~please_ack` decorator](../0317-please-ack/README.md) that invites [ACKs](../0317-please-ack/README.md#advanced-features-experimental) to be sent back from `invitee` to `inviter`, either at the time the invitation is accepted or at the time an outcome for the action is known, or both.

The `inviter` state machine looks like this:

[![inviter states](inviter_states.png)](inviter_states.puml)

The `invitee` state machine looks like this:

[![invitee states](invitee_states.png)](invitee_states.puml)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be useful to show in this state machine how a DIDComm protocol would be spawned off as a co-protocol (RFC0482)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll update.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a paragraph after the state machine of the invitee, explaining how this protocol would relate to a coprotocol or ordinary protocol invocation. I did not update the diagram itself. Please have a look and tell me what you think.

Copy link
Contributor

@llorllale llorllale Oct 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike Co-protocol Protocol, the Invite Action does not support ongoing yielding of intermediate outputs

I assumed the result(s) of the activity being invited to perform would depend solely on the goal code's semantics. There can exist a goal code involving streamed data or pushed data; this verbiage would restrict use solely to the provisioning of a streaming endpoint or a self-asserted credential that the invitee will push results on the clock every hour, respectively. I'm not sure we should preemptively limit our flexibility this way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Alice sends a goal code to Bob who is stranded on the side of the road with a flat tire, her goal might be to get him up and running... but Bob may also send an invite-action back asking for progress reports.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bob may also send an invite-action back asking for progress reports.

This is really interesting to me. It suggests that maybe we should have a progress reporting protocol. Right now, as written, I'm using advanced ACKs to address that need. Maybe that's suboptimal. Not sure. If we make progress reporting a protocol, then we also have to adjust the arity of invited actions, so that you invite agent X to take an action and also invite it to engage in a progress reporting protocol as the action unfolds. That starts to stray into the coprotocol protocol... But it's interesting to ponder.


During the time the `invitee` is in a `pending` state, a DIDComm protocol or coprotocol can be run, either to completion or to some desired status, depending on the semantics of the goal code. In such cases, the state of the `invitee` with respect to the protocol or coprotocol evolves, but the state of the `invitee` with respect to Invite Action remains `pending`. Unlike Co-protocol Protocol, the Invite Action does not support ongoing yielding of intermediate outputs, and there is no contract binding the `invitee` to expose the internals of its process or to cooperate with a `~please-ack` request at all. Complying with an ACK request is a courtesy, not a mandated behavior.


### Messages

The first message in the protocol (the only message that's required) is sent from `inviter` to `invitee`. An example might look like this:

```jsonc
{
"@id": "a3079284-9eed-4c76-8d39-a01c797b0e93",
"@type": "https://didcomm.org/invite-action/invite",
"goal_code": "automotive.inspect.tire",
"please_ack": {
"on": ["ACCEPT", "OUTCOME"]
}
}
```

This message suggests that the `invitee` take an action described by the [goal code](../../concepts/0519-goal-codes/README.md) `automotive.inspect.tire`, and asks the `invitee` to send back an ACK when the message is received, and another when the outcome of the action is known.

#### Adopted Messages

The generic [ACK](../0015-acks/README.md) message, version 1.0, is adopted into this protocol. This means the type of ACKs in this protocol should be:

>`https://didcomm.org/invite-action/%VER/ack`

## Reference

### Messages Details

The only unique field of an `invite` message is `goal_code`. The semantics of goal codes are described in [RFC 0519]. The `~please_ack` decorator is not required, but if present, it matches the semantics described in the [advanced section of RFC 0317](../0317-please-ack/README.md#advanced-features-experimental).

Some general-purpose mechanisms can also enrich this message:

* The `~timing.expires_time` decorator can be used to constrain how long the `inviter` will wait for an ACK.
* Individual goal codes can specify that they are to be accompanied by specific attachments. Then the generic DIDComm attachment mechanism can be used to pass data to the `invitee`.


## Drawbacks

Why should we *not* do this?

## Rationale and alternatives

- Why is this design the best in the space of possible designs?
- What other designs have been considered and what is the rationale for not
choosing them?
- What is the impact of not doing this?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you looked at "Action Menu"? I believe both this and Action Menu are trying to solve the exact same problem, but Action Menu does it in a more general way, allowing the user to see a menu of things they can do vs. just one, and allowing the invitee to include data as part of the request to act. Action Menu also allows the invitee to say "Hey, send me your menu so I can see what services you offer".

I think at least it should be included in the list of alternatives.

Copy link
Member Author

@dhh1128 dhh1128 Oct 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I have. As a matter of fact, I re-read its RFC before I started on this. I didn't see it as an exact equivalent, because it goes the opposite direction (agent willing to act proactively publishes a menu, instead of passively receiving an invitation). But I agree that it should be included in the list of alternatives.

Copy link
Member

@swcurran swcurran Oct 7, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds like we didn't explain it well. Action Menu was very much was intended to be either side starting the conversation, the "service-provider" offering a menu of options (could be just one as is the case here), and the "service-user" requesting the menu if necessary and on receipt, selecting what to use in moving forward.

We definitely need to get goal-code in into Action Menu, but I would be really interested in trying to merge these and make sure that we are covering the necessary cases. I think there is too much in common with these approaches.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a section to the comparison table talking about Action Menu. I identified the things that we might have to resolve to collapse the two.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the aspects of Action Menu that stand out to me:

  • allows one Agent to present a set of heirarchical menus and actions to another user-facing Agent in a human friendly way
  • requires an active DIDComm connection before it can proceed.
  • the responder presents a list of actions which can be initiated by the requester. Actions are contained within a menu structure.
  • can be initiated by either the requester asking for the root menu or the responder sending an unsolicited root menu.

It sounds a lot like RFC0031 "Discover Features Protocol" but a little bit more oriented towards enabling a human-friendly display of the actions. It also sounds a lot like a "service provider".

It makes sense for Action Menu to require a DIDComm connection between agents because, just like in RFC0031, an agent may wish to limit service exposure to un-trusted parties. An agent could theoretically send some sort of out-of-band menu request with a goal code and receive a tailored action menu in response. The agent would then need to take their pick.

It was hard for me to grok this inversion because normally human beings and software with logic just ask one another what to do with the expectation that the other party knows what they must do. The expectation is usually derived from the requester's context. If the requester now has to query a navigable menu received in response to the original request and then point the responder to the exact thing they'd like to be performed then that is adding a bit of overhead to the exchange.

Coming back to Daniel's auction example: Alice is auctioning a Rembrandt and would like to invite Bob to bid for it. She needs to send a message to Bob telling him the action, the subject, and the location. Bob either understands the message or he doesn't. He could reply with an Action Menu if he doesn't, but now Alice needs to understand Bob's action menu.

And I just realized something: the RFC proposed in this PR includes action (goal code) but does not include subject nor location. We're missing something here...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of thoughts on @llorllale comments:

  • Action Menu and Discover Features are not the same as Discover Features returns a list of protocols supported, while Action Menu is a list "business things you can do at this time". It's intended to be at a much higher layer. The fact that an agent supports "Issue credential" tells me nothing about what credentials are offered in the current context.

  • Action menus are not hierarchical, although a hierarchy can be constructed via a sequence of interactions. The telephone IVR system is the target -- at any point, the user gets a menu of things that they can do, including some that lead to other menus, others that lead to talking to a person for a specific reason, others that just send you to the operator.

The use of Action Menu will be needed when an Agent can be used to execute an entire business transaction vs. the current model we are seeing where the transaction is happening in a browser, and the agent is being used to provide a proof or receive a credential as a side-effect of the transaction. If you could use your agent to contact your bank and execute one of a set of transactions (check balance, transfer funds, open bank, get proof of balance), then the richer features of Action Menu become necessary.

Coming back to Daniel's auction, Alice could be auctioning a Rembrandt and present a menu of actions that Bob can take -- request proof of authenticity, see picture of painting, make a bid, request bid history, exit the bidding. And since, Alice is running an Auction house, Bob may start at a top menu allowing searching current auctions, see the painting of the day, pay invoice, talk to Alice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@swcurran

That all sounds good. The Action Menu RFC should be updated to enable all these use cases.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have begun a PR that would remove this RFC and update the Action Menu RFC. I'll try to finish that up.


## Prior art

See [Motivation](#motivation), which explains how this mechanism differs from some similar tools that are already available in the DIDComm ecosystem.

## Unresolved questions

- How will we integrate this mechanism with the rules of a governance framework?

## Implementations

> NOTE: This section should remain in the RFC as is on first release. Remove this note and leave the rest of the text as is. Template text in all other sections should be removed before submitting your Pull Request.

The following lists the implementations (if any) of this RFC. Please do a pull request to add your implementation. If the implementation is open source, include a link to the repo or to the implementation within the repo. Please be consistent in the "Name" field so that a mechanical processing of the RFCs can generate a list of all RFCs supported by an Aries implementation.

*Implementation Notes* [may need to include a link to test results](/README.md#accepted).

Name / Link | Implementation Notes
--- | ---
|
15 changes: 15 additions & 0 deletions features/0547-invite-action-protocol/invitee-states.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
@startuml
scale 350 width
[*] --> deciding
deciding --> [*]: ignore
deciding --> acting: invitation accepted
state acting {
[*] --> ack_at_pending: send ack\nat pending
[*] --> pending: no ack\nat pending
ack_at_pending --> pending
}
pending --> [*]: no ack\nat outcome
pending -->ack_at_outcome: send ack\nat outcome
ack_at_outcome --> [*]

@enduml
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions features/0547-invite-action-protocol/inviter-states.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@startuml
scale 350 width
[*] --> [*]: req no acks
[*] --> awaiting_ack_at_pending: req ack\nat pending
[*] --> awaiting_ack_at_outcome: req only ack\nat outcome
awaiting_ack_at_pending --> awaiting_ack_at_outcome: receive ack\nat pending
awaiting_ack_at_pending --> [*]: receive ack\nat outcome
awaiting_ack_at_outcome --> [*]: receive ack at outcome
@enduml
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions features/0547-invite-action-protocol/sequence.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
@startuml
Inviter -> Invitee: invite action with goal code, optional\npayload, optional ~please_ack
Invitee --> Inviter: (optional) initial ACK with status =\nPENDING
Invitee --> Inviter: (optional) final ACK with outcome,\noptional payload
@enduml