Skip to content

Conversation

@GregHolmes
Copy link
Contributor

Description

Add documentation for human-in-the-loop (HITL) workflows in AI Transport, covering how to implement human oversight of AI agent actions.

Topics covered:

  • Why human-in-the-loop matters (safety, compliance, trust, accountability)
  • Request-approval pattern over Ably channels
  • Using JWT claims and capabilities for authorization
  • Handling approval timeouts and rejections

@GregHolmes GregHolmes self-assigned this Jan 6, 2026
@GregHolmes GregHolmes added the review-app Create a Heroku review app label Jan 6, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 6, 2026

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ably-ci ably-ci temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 6, 2026 16:49 Inactive
@mschristensen mschristensen force-pushed the AIT-129-AIT-Docs-release-branch branch from aebe2c1 to ea0ac8d Compare January 7, 2026 11:48
Copy link
Contributor

@mschristensen mschristensen left a comment

Choose a reason for hiding this comment

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

Thanks Greg, needs a rebase but commented on the HITL doc page. Some good ideas in there but have flagged some bits for discussion, let me know if you want to catch up on the approach.

meta_keywords: "human in the loop, HITL, AI agent authorization, tool call approval, JWT claims, capabilities, admin approval, agentic workflows, AI safety, human oversight"
---

Human-in-the-loop (HITL) enables human oversight of AI agent actions. When an agent needs to perform sensitive operations, such as modifying data, making purchases, or accessing restricted resources, the action is paused and routed to an authorized human for approval before execution.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Human-in-the-loop (HITL) enables human oversight of AI agent actions. When an agent needs to perform sensitive operations, such as modifying data, making purchases, or accessing restricted resources, the action is paused and routed to an authorized human for approval before execution.
Human-in-the-loop (HITL) enables human oversight of AI agent actions. When an agent needs to perform sensitive operations, such as modifying data, performing sensitive actions, or accessing restricted resources, the action is paused and routed to an authorized human for approval before execution.


AI agents are increasingly capable of taking autonomous actions, but certain operations require human judgment:

- **Safety**: Prevent unintended consequences from AI decisions.
Copy link
Contributor

Choose a reason for hiding this comment

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

I know we need to update the other pages, but I think you (correctly) argued in the past that we should not use bold prefixes in bullets, which smells like an LLM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right! I asked Claude to review my work and improve where needed. I may have missed this! Updated.

- **Trust**: Build user confidence by keeping humans in control of critical actions.
- **Accountability**: Create clear audit trails of who approved what actions.

HITL doesn't slow down AI — it ensures the right actions happen at the right time with appropriate oversight.
Copy link
Contributor

Choose a reason for hiding this comment

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

This feels like typical AI word salad, how about:

Suggested change
HITL doesn't slow down AI — it ensures the right actions happen at the right time with appropriate oversight.
HITL puts a human approval step in front of agent actions that carry risk or uncertainty.


## Why human-in-the-loop matters <a id="why-hitl"/>

AI agents are increasingly capable of taking autonomous actions, but certain operations require human judgment:
Copy link
Contributor

Choose a reason for hiding this comment

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

An additional point thats not captured here - sometimes HITL is useful when the agent needs to more clarification or human input before taking further action.

Human-in-the-loop authorization follows a request-approval pattern over Ably channels:

1. The AI agent determines a tool call requires human approval.
2. The agent publishes an authorization request to a dedicated channel.
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, I'm not sure we need to use a dedicated channel (with capabilities on hitl:* etc). Why not just sent the HITL request from the agent on the same channel? The agent is going to do a lookup when it gets the response from the user anyway to determine if it is allowed to make that decision, so I don't think these needs to be enforced at the Ably channel level?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I had to make a few changes elsewhere as the page was more focused on dedicated channel capabilities etc. So I've stuck it (and the couple changes recommended above) into a single fixup: d2c24d0

This may change depending on your feedback below though.


## Request human approval <a id="request"/>

When an agent identifies an action requiring human oversight, it publishes a request to a HITL channel. The request should include sufficient context for the approver to make an informed decision, including the action name, parameters, a human-readable reason, and the risk level.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is a bit overly opinionated - I don't think all HITL loops need to carry a risk level or a reason?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've removed the opinionated bits from this section including updating the code:

8dd7f22


When an agent identifies an action requiring human oversight, it publishes a request to a HITL channel. The request should include sufficient context for the approver to make an informed decision, including the action name, parameters, a human-readable reason, and the risk level.

Include an expiry time to prevent stale requests from being approved after circumstances have changed. The `requestId` enables correlation between requests and responses when handling multiple concurrent approval flows.
Copy link
Contributor

Choose a reason for hiding this comment

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

Again I think this is getting too opinionated about how to implement HITL flows. Instead, this doc should focus on the core Ably primitives you would rely on to implement HITL.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this was covered in the comment above.

```
</Code>

## Review and decide <a id="review"/>
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here. I think the doc should just cover an agent sending a HITL request to a user, and obtaining the response from the user (with verified identity/role etc) and taking an action accordingly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've removed all the opinionated work from this section: 901564a


The agent listens for human decisions and acts accordingly. When a response arrives, the agent retrieves the pending request using the `requestId`, verifies the approver's identity and role from the trusted JWT claims, and either executes the action or notifies the user of the rejection.

Logging all decisions with the approver's identity and role creates an audit trail. This is essential for compliance, debugging, and understanding how the system is being used over time.
Copy link
Contributor

Choose a reason for hiding this comment

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

Application logging is a customer's concern, unrelated to Ably, and doesn't need to be documented here.

However, an Ably primitive that might be relevant to audit trails is integration rules, which I think would be valid to call out here (although I think a brief mention and link to integration rule docs is sufficient, rather than a full fledged example).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated in the last 3 fixups.

```
</Code>

## Handle timeouts <a id="timeout"/>
Copy link
Contributor

Choose a reason for hiding this comment

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

Again I think this is an implementation question, possible suitable for a guide, but not for feature documentation.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed, I've removed this section in 0a3c7a1

@paddybyers
Copy link
Member

This looks like it needs the base branch changing

@GregHolmes GregHolmes force-pushed the AIT-105-Feature-documentation-human-in-the-loop-workflow branch from 4bf0fe2 to 4cade76 Compare January 8, 2026 10:30
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 10:30 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 16:26 Inactive
@GregHolmes GregHolmes had a problem deploying to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 16:50 Failure
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 16:53 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 16:59 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 17:03 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 17:19 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 17:21 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 8, 2026 17:22 Inactive
@GregHolmes
Copy link
Contributor Author

Thank you @mschristensen I've updated from your feedback.

@paddybyers I think Mike rebased the release branch with main, which then left my PR here outdated. But I didn't see as was off yesterday. All rebased now. Thanks for flagging.

Copy link
Contributor

@mschristensen mschristensen left a comment

Choose a reason for hiding this comment

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

Thanks Greg, looks good, a few last comments

│ subscribe: approval-response │ publish: approval-response
│ │
▼ ▼
```
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we should remove this ASCII diagram, until we have nicely designed ones. I created a ticket: https://ably.atlassian.net/browse/AIT-257

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you. I didn't think the ASCII would be a releaseable piece to show but more something that could assist design on any images we'd need to create.

c8d3d5e

▼ ▼
```

## Verify approver permissions <a id="verify"/>
Copy link
Contributor

Choose a reason for hiding this comment

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

This section appears twice. This one should be removed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yep! I think I forgot to remove when I moved things around: 2abee1a


## Verify approver permissions <a id="verify"/>

Use the trusted `userClaim` from the JWT to verify the approver has sufficient permissions for the specific action. Different actions may require different authorization levels — a moderator might approve content-related actions while financial operations require an admin.
Copy link
Contributor

Choose a reason for hiding this comment

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

We shouldn't use an em-dash, which is a tell-tale sign of AI generated content

Suggested change
Use the trusted `userClaim` from the JWT to verify the approver has sufficient permissions for the specific action. Different actions may require different authorization levels a moderator might approve content-related actions while financial operations require an admin.
Use the trusted `userClaim` from the JWT to verify the approver has sufficient permissions for the specific action. Different actions may require different authorization levels - for example, a moderator might approve content-related actions while financial operations require an admin.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

cb77913

Updated!

if (!pending) return;

// The clientId is verified by Ably - this is the trusted approver identity
const approverId = message.clientId;
Copy link
Contributor

Choose a reason for hiding this comment

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

We havent shown how to use identified clients or, as used later in this doc, roles. We should document a minimal example of the JWT claims, like we do in the accepting user input docs, and include relevant links to the sessions & identity docs

Copy link
Contributor 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 new h3 within Process the decision called Verify approver identity. Let me know what you think: 3a0588e

```
</Code>

## Complete example <a id="example"/>
Copy link
Contributor

Choose a reason for hiding this comment

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

We haven't included this in other docs pages, and I'm not convinced it's necessary; the docs up to this point should be easy enough to follow that it's not required. A complete example imposes certain decisions on the implementation which prior docs aimed to discuss in more nuanced detail, allowing the reader to decide what is appropriate for them. This seems more suitable for a guide.

However, let me know if you disagree (and if you do, we should consider whether other docs pages need an equivalent section, and we should ticket that).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, it shouldn't be here. I've now removed: d1bfedb

We're going to cover this type of thing in the guides so there's no need in feature pages.

@GregHolmes GregHolmes force-pushed the AIT-105-Feature-documentation-human-in-the-loop-workflow branch from b4b4b2e to 87ebceb Compare January 12, 2026 11:20
@GregHolmes GregHolmes had a problem deploying to ably-docs-ait-105-featu-zrkjv1 January 12, 2026 11:20 Failure
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 12, 2026 11:21 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 12, 2026 11:23 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 12, 2026 11:24 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 12, 2026 11:25 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 12, 2026 13:40 Inactive
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 13, 2026 11:23 Inactive
2. The agent publishes an authorization request to the conversation channel.
3. An authorized user receives and reviews the request.
4. The human approves or rejects the request.
5. The agent receives the decision, verifies the responder's role via [user claims](/docs/ai-transport/features/sessions-identity/identifying-users-and-agents#user-claims), and proceeds accordingly.
Copy link
Contributor

Choose a reason for hiding this comment

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

The mechanism could be either role (via user claims) or just the verified identity (via identified clients), so I think it's ok to just state:

Suggested change
5. The agent receives the decision, verifies the responder's role via [user claims](/docs/ai-transport/features/sessions-identity/identifying-users-and-agents#user-claims), and proceeds accordingly.
5. The agent receives the decision, verifies the responder's identity or role and proceeds accordingly.

...since the detail is covered later in the document.


<Code>
```javascript
const channel = ably.channels.get('conversation:session-123');
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
const channel = ably.channels.get('conversation:session-123');
const channel = ably.channels.get('{{RANDOM_CHANNEL_NAME}}');

Human-in-the-loop authorization follows a request-approval pattern over Ably channels:

1. The AI agent determines a tool call requires human approval.
2. The agent publishes an authorization request to the conversation channel.
Copy link
Contributor

Choose a reason for hiding this comment

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

Everywhere we say "conversation channel", I think we should just say "channel"

Suggested change
2. The agent publishes an authorization request to the conversation channel.
2. The agent publishes an authorization request to the channel.


## Request human approval <a id="request"/>

When an agent identifies an action requiring human oversight, it publishes a request to the conversation channel. The request should include sufficient context for the approver to make an informed decision. The `requestId` enables correlation between requests and responses when handling multiple concurrent approval flows.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
When an agent identifies an action requiring human oversight, it publishes a request to the conversation channel. The request should include sufficient context for the approver to make an informed decision. The `requestId` enables correlation between requests and responses when handling multiple concurrent approval flows.
When an agent identifies an action requiring human oversight, it publishes a request to the channel. The request should include sufficient context for the approver to make an informed decision. The `requestId` enables correlation between requests and responses when handling multiple concurrent approval flows.

@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 13, 2026 11:45 Inactive
@ably-ci ably-ci temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 13, 2026 12:25 Inactive
Document how to implement human oversight of AI agent actions using
Ably channels and capabilities for authorization workflows.
@GregHolmes GregHolmes force-pushed the AIT-105-Feature-documentation-human-in-the-loop-workflow branch from 761aa6e to 9915388 Compare January 13, 2026 12:40
@GregHolmes GregHolmes temporarily deployed to ably-docs-ait-105-featu-zrkjv1 January 13, 2026 12:40 Inactive
@GregHolmes GregHolmes merged commit 4822c97 into AIT-129-AIT-Docs-release-branch Jan 13, 2026
7 checks passed
@GregHolmes GregHolmes deleted the AIT-105-Feature-documentation-human-in-the-loop-workflow branch January 13, 2026 12:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-app Create a Heroku review app

Development

Successfully merging this pull request may close these issues.

5 participants