Skip to content

LCORE-1589: Human-in-the-Loop Spike#1459

Open
jrobertboos wants to merge 2 commits intolightspeed-core:mainfrom
jrobertboos:lcore-1589-spike-human-in-the-loop
Open

LCORE-1589: Human-in-the-Loop Spike#1459
jrobertboos wants to merge 2 commits intolightspeed-core:mainfrom
jrobertboos:lcore-1589-spike-human-in-the-loop

Conversation

@jrobertboos
Copy link
Copy Markdown
Contributor

@jrobertboos jrobertboos commented Apr 6, 2026

Description

Type of change

  • Refactor
  • New feature
  • Bug fix
  • CVE fix
  • Optimization
  • Documentation Update
  • Configuration Update
  • Bump-up service version
  • Bump-up dependent library
  • Bump-up library or tool used for development (does not change the final image)
  • CI configuration change
  • Konflux configuration change
  • Unit tests improvement
  • Integration tests improvement
  • End to end tests improvement
  • Benchmarks improvement

Tools used to create PR

Identify any AI code assistants used in this PR (for transparency and review context)

  • Assisted-by: (e.g., Claude, CodeRabbit, Ollama, etc., N/A if not used)
  • Generated by: (e.g., tool name and version; N/A if not used)

Related Tickets & Documents

  • Related Issue #
  • Closes #

Checklist before requesting a review

  • I have performed a self-review of my code.
  • PR has passed all pre-merge test jobs.
  • If it is a core feature, I have added thorough tests.

Testing

  • Please provide detailed steps to perform tests related to this code change.
  • How were the fix/results from this change verified? Please provide relevant screenshots or results.

Summary by CodeRabbit

  • Documentation
    • Added design documentation for Human-in-the-Loop approval workflow for MCP tool operations.
    • Covers asynchronous approval mechanism, API endpoints, storage strategy, and configuration options.
    • Includes implementation specifications, security considerations, and backwards compatibility details.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

Walkthrough

Adds two Human-in-the-Loop (HIL) design documents defining an asynchronous approval workflow for MCP tool calling: a spike exploring design decisions and a full specification covering control flow, API endpoints, data models, configuration, error handling, and implementation tasks.

Changes

Cohort / File(s) Summary
Human-in-the-Loop Design Docs
docs/design/human-in-the-loop/human-in-the-loop-spike.md, docs/design/human-in-the-loop/human-in-the-loop.md
Adds a 448-line spike and a comprehensive spec (~558 lines) defining asynchronous MCP approval flow, new requires_action response shape, /approvals API (GET/POST), approval request storage (cache or new approval_requests table schemas), TTL and expiry behavior, require_approval configuration (default "never"), allow/deny permanence semantics, error/status codes, authz expectations, streaming behavior, and an engineering implementation roadmap including tests and docs updates.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant LCS as LCS (server)
  participant Llama as Llama Stack (agent)
  participant Store as Approval Storage (cache/DB)
  participant MCP as MCP Tool/Server

  Client->>LCS: query/stream request (may invoke MCP)
  LCS->>Llama: forward request
  Llama->>LCS: emits mcp_approval_request (requires_action)
  LCS->>Store: persist approval request (TTL)
  LCS-->>Client: HTTP 200 / stream event with status:"requires_action" + required_action
  Client->>LCS: POST /approvals/{id} (approve/deny)
  LCS->>Store: validate & fetch approval request
  LCS->>Llama: send mcp_approval_response (approved/denied)
  alt approved
    Llama->>MCP: resume/execute MCP call
    MCP->>Llama: tool response
    Llama->>LCS: final output / continue stream
    LCS-->>Client: return/stream result
  else denied
    Llama->>LCS: handle denial (terminate or continue)
    LCS-->>Client: return error/status update
  end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title references a ticket (LCORE-1589) and mentions 'Human-in-the-Loop Spike', which aligns with the changes (design spike documents for Human-in-the-Loop approval). However, it uses a vague term 'Spike' without clarifying the core feature being designed, making it less descriptive than ideal for historical context.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
✨ Simplify code
  • Create PR with simplified code

Warning

Review ran into problems

🔥 Problems

Timed out fetching pipeline failures after 30000ms


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.

@jrobertboos jrobertboos marked this pull request as ready for review April 6, 2026 15:41
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/design/human-in-the-loop/human-in-the-loop-spike.md`:
- Around line 137-139: Replace all placeholder ticket keys "LCORE-????" in this
document (notably in the story header "Add `require_approval` configuration for
MCP servers" and the other repeated headings/keys) with real issue keys or
explicitly mark them as TODO outside merge scope; update every instance so the
design links to a traceable ticket and regenerate any related anchors/README
references if used to ensure cross-references remain valid.
- Line 72: Fix the markdown fence lint violations by adding explicit language
identifiers to all fenced code blocks and ensuring required blank lines before
and after each fence; e.g., replace bare/unnamed fences near the table row
containing | B. "always" | Secure by default, opt-out for trusted tools | and
the suggested fences like ```text and ```sql with properly spaced fences (blank
line above and below) and add a language tag (e.g., ```text, ```sql) so every
fenced block in human-in-the-loop-spike.md (also at the other listed
occurrences) follows markdownlint MD040/MD031 rules.

In `@docs/design/human-in-the-loop/human-in-the-loop.md`:
- Around line 337-355: The docs introduce a new "requires_action" response shape
for /query and /streaming_query (payload keys like conversation_id,
status="requires_action", required_action.type="mcp_approval", approvals[] with
id/server_label/tool_name/arguments/expires_at) but the doc still claims "No API
changes"; update the API contract by explicitly modeling the response as a
union/oneOf (e.g., QueryResponse = oneOf{QueryResult, RequiresActionResult}) or
call out version-gating; clearly list both shapes and add OpenAPI/typed-client
guidance so consumers of query and streaming_query know to handle both variants
(or upgrade the endpoint version).
- Around line 307-309: Choose one authorization error semantics (either "403
Forbidden for unauthorized/ownership failures" or "404 Not Found for not owned
by user") and apply it consistently: update the lines containing "Response
(404): Approval not found or not owned by user" and any other endpoint
descriptions that mention ownership/authorization to use the chosen status, and
update the error matrix entry that currently lists 403 so it matches. Search for
the exact phrase "Approval not found or not owned by user" and the error-matrix
rows that mention 403/404 (sections referenced around the existing text) and
change the status codes and any explanatory text so all endpoint sections and
the matrix use the same policy.
- Around line 392-393: Update the phrasing in the "5. **Rate limiting**" bullet
so the sentence reads "Approval endpoints should be rate-limited to prevent
abuse (handled by existing rate limiting infrastructure)." — find the bullet
titled "Rate limiting" and replace the unhyphenated "should be rate limited" (or
similar) with the hyphenated "should be rate-limited" to ensure grammatical
consistency.
- Around line 93-103: The approval continuation flow is ambiguous: clarify
whether POST /approvals/{id} resumes the agent and returns the assistant's final
output or if the client must call /query again. Update human-in-the-loop.md (and
the related diagram lines ~310-329) to explicitly state the contract for POST
/approvals/{id}: either (A) POST /approvals/{id} returns 200 with approval
metadata plus resumed agent output in a named field (e.g., mcp_approval_response
includes "resumed_output" or "final_response" and any tool result), or (B) POST
/approvals/{id} returns only approval status metadata and the client is required
to re-issue a GET/POST to /query to retrieve the agent’s continued output. Pick
one behavior, update the sequence diagram labels (mcp_approval_response, tool
result + response) and document exact JSON shape and status codes for the chosen
contract so clients know how to continue.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9d842f74-dc75-4099-be6a-11e98dcf5265

📥 Commits

Reviewing files that changed from the base of the PR and between 7b29914 and 6d6f244.

📒 Files selected for processing (2)
  • docs/design/human-in-the-loop/human-in-the-loop-spike.md
  • docs/design/human-in-the-loop/human-in-the-loop.md
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Konflux kflux-prd-rh02 / lightspeed-stack-on-pull-request
  • GitHub Check: E2E: server mode / ci
🧰 Additional context used
🪛 LanguageTool
docs/design/human-in-the-loop/human-in-the-loop.md

[style] ~61-~61: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...re interaction - U3: As a user, I want to see what a tool will do before it runs,...

(REP_WANT_TO_VB)


[style] ~63-~63: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...unwanted changes - U4: As a user, I want to deny a tool invocation, so that I can s...

(REP_WANT_TO_VB)


[grammar] ~393-~393: Use a hyphen to join words.
Context: ...event abuse (handled by existing rate limiting infrastructure). ### Migration...

(QB_NEW_EN_HYPHEN)

🪛 markdownlint-cli2 (0.22.0)
docs/design/human-in-the-loop/human-in-the-loop-spike.md

[warning] 72-72: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


[warning] 128-128: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 150-150: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 272-272: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 294-294: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 315-315: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 323-323: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 338-338: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 358-358: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

| Option | Description |
|--------|-------------|
| A. `"never"` (current behavior) | Backwards compatible, opt-in HIL |
| B. `"always"` | Secure by default, opt-out for trusted tools |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix markdown fence lint violations (MD040/MD031).

There is at least one fenced block without a language (Line 72) and multiple fences missing required blank lines around them. This will keep docs lint noisy/failing where markdownlint is enforced.

Suggested doc cleanup
-```
+```text
 ...
-```
+```

+ 
 ```sql
 ...
</details>




Also applies to: 128-128, 150-150, 272-272, 294-294, 315-315, 323-323, 338-338, 358-358

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.22.0)</summary>

[warning] 72-72: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/design/human-in-the-loop/human-in-the-loop-spike.md at line 72, Fix the
markdown fence lint violations by adding explicit language identifiers to all
fenced code blocks and ensuring required blank lines before and after each
fence; e.g., replace bare/unnamed fences near the table row containing | B.
"always" | Secure by default, opt-out for trusted tools | and the suggested
fences like text and sql with properly spaced fences (blank line above and
below) and add a language tag (e.g., text, sql) so every fenced block in
human-in-the-loop-spike.md (also at the other listed occurrences) follows
markdownlint MD040/MD031 rules.


</details>

<!-- fingerprinting:phantom:triton:hawk:9b03e7ec-f5cf-4fea-8293-25b4eb3bd5f8 -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +137 to +139
<!-- type: Story -->
<!-- key: LCORE-???? -->
### LCORE-???? Add `require_approval` configuration for MCP servers
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace placeholder ticket keys before merge.

LCORE-???? placeholders make the execution plan non-actionable and break traceability from design to delivery. Please resolve these to real issue keys (or explicitly mark as TODO outside merge scope).

Also applies to: 167-169, 194-196, 222-224, 250-253, 275-277, 301-304

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop-spike.md` around lines 137 -
139, Replace all placeholder ticket keys "LCORE-????" in this document (notably
in the story header "Add `require_approval` configuration for MCP servers" and
the other repeated headings/keys) with real issue keys or explicitly mark them
as TODO outside merge scope; update every instance so the design links to a
traceable ticket and regenerate any related anchors/README references if used to
ensure cross-references remain valid.

Comment on lines +93 to +103
│ │ POST /approvals/{id} │ │
│ │ ────────────────────────────► │
│ │ {approve: true} │ │
│ │ │ │
│ │ │ ───── mcp_approval_response ──────────►│
│ │ │ │
│ │ │ ◄────── tool result + response ────────┤
│ │ │ │
│ │ ◄─── 200 OK ────────────────┤ │
│ │ (final response) │ │
│ │
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Approval continuation flow is ambiguous after POST /approvals/{id}.

The diagram implies a final assistant response is returned after approval, but the endpoint example returns only approval status metadata. Please define the exact continuation contract (e.g., whether client must call /query again, or approval endpoint can return resumed agent output).

Also applies to: 310-329

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop.md` around lines 93 - 103,
The approval continuation flow is ambiguous: clarify whether POST
/approvals/{id} resumes the agent and returns the assistant's final output or if
the client must call /query again. Update human-in-the-loop.md (and the related
diagram lines ~310-329) to explicitly state the contract for POST
/approvals/{id}: either (A) POST /approvals/{id} returns 200 with approval
metadata plus resumed agent output in a named field (e.g., mcp_approval_response
includes "resumed_output" or "final_response" and any tool result), or (B) POST
/approvals/{id} returns only approval status metadata and the client is required
to re-issue a GET/POST to /query to retrieve the agent’s continued output. Pick
one behavior, update the sequence diagram labels (mcp_approval_response, tool
result + response) and document exact JSON shape and status codes for the chosen
contract so clients know how to continue.

Comment on lines +307 to +309
Response (404): Approval not found or not owned by user
Response (410): Approval expired

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Resolve conflicting authorization error semantics (404 vs 403).

Line 307/331 state “not found or not owned by user” as 404, but the error matrix includes 403 forbidden for unauthorized access. Pick one policy and apply it consistently across endpoint sections and the matrix.

Also applies to: 331-334, 369-375

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop.md` around lines 307 - 309,
Choose one authorization error semantics (either "403 Forbidden for
unauthorized/ownership failures" or "404 Not Found for not owned by user") and
apply it consistently: update the lines containing "Response (404): Approval not
found or not owned by user" and any other endpoint descriptions that mention
ownership/authorization to use the chosen status, and update the error matrix
entry that currently lists 403 so it matches. Search for the exact phrase
"Approval not found or not owned by user" and the error-matrix rows that mention
403/404 (sections referenced around the existing text) and change the status
codes and any explanatory text so all endpoint sections and the matrix use the
same policy.

Comment on lines +337 to +355
Query and streaming_query endpoints may return:
```json
{
"conversation_id": "conv_xyz",
"status": "requires_action",
"required_action": {
"type": "mcp_approval",
"approvals": [
{
"id": "apr_abc123",
"server_label": "github-mcp",
"tool_name": "create_issue",
"arguments": {"title": "Bug report", "body": "..."},
"expires_at": "2026-04-01T10:05:00Z"
}
]
}
}
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Clarify response contract and versioning for requires_action.

This introduces a second response shape for /query/streaming while Line 401 says “No API changes to existing endpoints.” That is effectively an API contract change for typed clients and OpenAPI consumers. Please explicitly define this as a union/oneOf response model (or version-gate it) to avoid runtime/client breakage.

Also applies to: 397-402

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop.md` around lines 337 - 355,
The docs introduce a new "requires_action" response shape for /query and
/streaming_query (payload keys like conversation_id, status="requires_action",
required_action.type="mcp_approval", approvals[] with
id/server_label/tool_name/arguments/expires_at) but the doc still claims "No API
changes"; update the API contract by explicitly modeling the response as a
union/oneOf (e.g., QueryResponse = oneOf{QueryResult, RequiresActionResult}) or
call out version-gating; clearly list both shapes and add OpenAPI/typed-client
guidance so consumers of query and streaming_query know to handle both variants
(or upgrade the endpoint version).

Comment on lines +392 to +393
5. **Rate limiting**: Approval endpoints should be rate-limited to prevent
abuse (handled by existing rate limiting infrastructure).
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use hyphenated “rate-limited” phrasing.

Line 393 should read “should be rate-limited” for grammar consistency.

🧰 Tools
🪛 LanguageTool

[grammar] ~393-~393: Use a hyphen to join words.
Context: ...event abuse (handled by existing rate limiting infrastructure). ### Migration...

(QB_NEW_EN_HYPHEN)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop.md` around lines 392 - 393,
Update the phrasing in the "5. **Rate limiting**" bullet so the sentence reads
"Approval endpoints should be rate-limited to prevent abuse (handled by existing
rate limiting infrastructure)." — find the bullet titled "Rate limiting" and
replace the unhyphenated "should be rate limited" (or similar) with the
hyphenated "should be rate-limited" to ensure grammatical consistency.

for trusted tools.

**PoC validation**: Not yet built. The core mechanism (Llama Stack approval
types) is already implemented and tested in the codebase.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

which code base exactly? llama-stack or LCS?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

in this case llama stack but this part is not needed

Comment on lines +51 to +63
### Decision 3: Permanent allow/deny list storage

Where should permanent tool allow/deny lists be configured?

| Option | Description |
|--------|-------------|
| A. Database only | Runtime configuration, managed via API |
| B. YAML config only | Deployment-time configuration |
| C. Both | YAML baseline with database overrides |

**Recommendation**: Option B (YAML config only). Keeps security policy
declarative and auditable. Runtime overrides can be added in a future iteration
if customer demand exists.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need to have permanent allow/deny list of tools/actions for an MCP server in the initial implementation of the /approval API?

Especially if Decision 2 is "C. Per-request | Each tool invocation requires separate approval", sounds like we can keep things simple for the first implementation, and come back and implement features like "allow/deny lists" at a later point?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Well we will definitely need an allow/deny list of some sort in order for our users to configure the HITL settings for each mcp server. Because for example a log reading tool might not need HITL approval while a tool that is potentially destructive must have some sort of HITL.

Comment on lines +74 to +75
**Recommendation**: Option A (`"never"`). Maintains backwards compatibility.
Operators explicitly enable HIL for servers with write operations.
Copy link
Copy Markdown
Contributor

@anik120 anik120 Apr 6, 2026

Choose a reason for hiding this comment

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

Are we concerned with backward compatibility yet? If we're still in the prototype landscape with our clients, is it better to switch this to "always" so that this change is more immediately surfaced to our clients?

├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────┐ POST /query ┌─────────────────┐ responses.create ┌───────────┐
│ │ Client │ ───────────────► │ LCS Query │ ───────────────────► │ Llama │
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is the Client here an MCP server?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Client is LS App team.

Comment on lines +129 to +141
CREATE TABLE IF NOT EXISTS approval_requests (
id TEXT PRIMARY KEY,
conversation_id TEXT NOT NULL,
user_id TEXT NOT NULL,
server_label TEXT NOT NULL,
tool_name TEXT NOT NULL,
arguments TEXT NOT NULL, -- JSON
status TEXT NOT NULL DEFAULT 'pending', -- pending, approved, denied, expired
created_at TEXT NOT NULL,
expires_at TEXT NOT NULL,
decision_reason TEXT,
decided_at TEXT
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What'll be the policy for clearing up this table? I understand that when an approval is required, a new row will be created to keep track of this particular request along with all other pending requests. Should we also explicitly state once a response is received from the client (approval/denial), we will delete the row to ensure database doesn't get bloated with outdated data?

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (4)
docs/design/human-in-the-loop/human-in-the-loop.md (3)

93-103: ⚠️ Potential issue | 🟠 Major

Clarify the continuation contract after POST /approvals/{id}.

The doc still implies two behaviors (approval endpoint returns final response vs client must re-query). Define one explicit contract and keep examples/diagram consistent.

Also applies to: 322-329, 556-558

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop.md` around lines 93 - 103,
The documentation is ambiguous about whether POST /approvals/{id} returns the
final response or requires the client to re-query; pick one behavior and update
the contract and diagrams to match: if you choose synchronous final response,
state that POST /approvals/{id} returns 200 with the final tool result
(mcp_approval_response) and remove any arrows/notes implying re-query; if you
choose asynchronous, state that POST /approvals/{id} returns an acknowledgment
and clients must GET /approvals/{id} (or another polling/webhook) to receive the
final tool result, and update the diagram and all examples (references to POST
/approvals/{id}, mcp_approval_response, and "tool result + response") to
consistently reflect that single chosen flow.

337-355: ⚠️ Potential issue | 🟠 Major

Document /query/streaming_query as a response union instead of “no API changes.”

Adding requires_action introduces a new response variant; this is an API contract change for typed consumers and should be modeled explicitly.

Also applies to: 397-402

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop.md` around lines 337 - 355,
The docs currently state “no API changes” but the addition of the
requires_action response is a new response variant for the /query and
/streaming_query endpoints; update the documentation in human-in-the-loop.md to
document the endpoints’ response as a union type that includes the new
requires_action shape (with conversation_id, status, and
required_action.mcp_approval structure including approvals items and expires_at)
instead of claiming no API changes, and add the same union-style documentation
for the other occurrence referenced (around lines ~397-402) so typed consumers
can see the new contract.

307-308: ⚠️ Potential issue | 🟠 Major

Unify authorization semantics (404 vs 403) across endpoint docs and error matrix.

The endpoint sections and error table still conflict on ownership/authorization failures. Pick one policy and apply it consistently.

Also applies to: 331-332, 369-375

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop.md` around lines 307 - 308,
The docs currently mix 404 and 403 for authorization/ownership failures (e.g.,
the lines "Response (404): Approval not found or not owned by user" and
"Response (410): Approval expired"); pick one canonical policy (recommend using
403 for "not owned/forbidden" and 404 only for truly non-existent resources) and
apply it consistently across the endpoint descriptions and the error matrix
including the other affected sections (around the blocks noted at 331-332 and
369-375); update the response codes and any corresponding error text so all
references to ownership/authorization failures use the chosen status code and
adjust examples/messages to match.
docs/design/human-in-the-loop/human-in-the-loop-spike.md (1)

138-139: ⚠️ Potential issue | 🟠 Major

Replace unresolved LCORE-???? placeholders with real ticket IDs before merge.

These placeholders still make the implementation plan non-actionable and untraceable to delivery work items.

Also applies to: 167-168, 194-195, 222-223, 251-252, 276-277, 302-303

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop-spike.md` around lines 138 -
139, Replace every unresolved placeholder "LCORE-????" in this document (e.g.,
the heading "### LCORE-???? Add `require_approval` configuration for MCP
servers" and the other repeated occurrences) with the actual ticket/issue IDs
that track the work; update all instances so the headings and inline keys
reference real, authoritative ticket numbers before merging.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/design/human-in-the-loop/human-in-the-loop.md`:
- Around line 72-105: The ASCII diagram code fence in the human-in-the-loop doc
is unlabeled and triggers markdown lint; update the fenced block around the
Request Flow diagram in human-in-the-loop.md by adding a language identifier
(e.g., ```text) to the opening fence so the diagram is treated as plain text and
linting passes, leaving the content unchanged.

---

Duplicate comments:
In `@docs/design/human-in-the-loop/human-in-the-loop-spike.md`:
- Around line 138-139: Replace every unresolved placeholder "LCORE-????" in this
document (e.g., the heading "### LCORE-???? Add `require_approval` configuration
for MCP servers" and the other repeated occurrences) with the actual
ticket/issue IDs that track the work; update all instances so the headings and
inline keys reference real, authoritative ticket numbers before merging.

In `@docs/design/human-in-the-loop/human-in-the-loop.md`:
- Around line 93-103: The documentation is ambiguous about whether POST
/approvals/{id} returns the final response or requires the client to re-query;
pick one behavior and update the contract and diagrams to match: if you choose
synchronous final response, state that POST /approvals/{id} returns 200 with the
final tool result (mcp_approval_response) and remove any arrows/notes implying
re-query; if you choose asynchronous, state that POST /approvals/{id} returns an
acknowledgment and clients must GET /approvals/{id} (or another polling/webhook)
to receive the final tool result, and update the diagram and all examples
(references to POST /approvals/{id}, mcp_approval_response, and "tool result +
response") to consistently reflect that single chosen flow.
- Around line 337-355: The docs currently state “no API changes” but the
addition of the requires_action response is a new response variant for the
/query and /streaming_query endpoints; update the documentation in
human-in-the-loop.md to document the endpoints’ response as a union type that
includes the new requires_action shape (with conversation_id, status, and
required_action.mcp_approval structure including approvals items and expires_at)
instead of claiming no API changes, and add the same union-style documentation
for the other occurrence referenced (around lines ~397-402) so typed consumers
can see the new contract.
- Around line 307-308: The docs currently mix 404 and 403 for
authorization/ownership failures (e.g., the lines "Response (404): Approval not
found or not owned by user" and "Response (410): Approval expired"); pick one
canonical policy (recommend using 403 for "not owned/forbidden" and 404 only for
truly non-existent resources) and apply it consistently across the endpoint
descriptions and the error matrix including the other affected sections (around
the blocks noted at 331-332 and 369-375); update the response codes and any
corresponding error text so all references to ownership/authorization failures
use the chosen status code and adjust examples/messages to match.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 22330491-d6b6-4565-b487-db4717d039c7

📥 Commits

Reviewing files that changed from the base of the PR and between 6d6f244 and 0ed23a6.

📒 Files selected for processing (2)
  • docs/design/human-in-the-loop/human-in-the-loop-spike.md
  • docs/design/human-in-the-loop/human-in-the-loop.md
📜 Review details
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2026-04-05T12:19:36.009Z
Learnt from: CR
Repo: lightspeed-core/lightspeed-stack PR: 0
File: AGENTS.md:0-0
Timestamp: 2026-04-05T12:19:36.009Z
Learning: Applies to src/**/*.py : Use `from llama_stack_client import AsyncLlamaStackClient` for Llama Stack imports

Applied to files:

  • docs/design/human-in-the-loop/human-in-the-loop-spike.md
🪛 LanguageTool
docs/design/human-in-the-loop/human-in-the-loop.md

[style] ~61-~61: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...re interaction - U3: As a user, I want to see what a tool will do before it runs,...

(REP_WANT_TO_VB)


[style] ~63-~63: You have already used this phrasing in nearby sentences. Consider replacing it to add variety to your writing.
Context: ...unwanted changes - U4: As a user, I want to deny a tool invocation, so that I can s...

(REP_WANT_TO_VB)


[grammar] ~393-~393: Use a hyphen to join words.
Context: ...event abuse (handled by existing rate limiting infrastructure). ### Migration...

(QB_NEW_EN_HYPHEN)

Comment on lines +72 to +105
```
┌──────────────────────────────────────────────────────────────────────────────┐
│ Request Flow │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌────────┐ POST /query ┌─────────────────┐ responses.create ┌───────────┐
│ │ Client │ ───────────────► │ LCS Query │ ───────────────────► │ Llama │
│ │ │ │ Endpoint │ │ Stack │
│ └────────┘ └─────────────────┘ └───────────┘
│ │ │ │
│ │ │ ◄─────── mcp_approval_request ─────────┤
│ │ │ │
│ │ ┌──────▼──────┐ │
│ │ │ Store │ │
│ │ │ Approval │ │
│ │ │ Request │ │
│ │ └──────┬──────┘ │
│ │ │ │
│ │ ◄─── 200 OK ────────────────┤ │
│ │ status: requires_action│ │
│ │ │ │
│ │ POST /approvals/{id} │ │
│ │ ────────────────────────────► │
│ │ {approve: true} │ │
│ │ │ │
│ │ │ ───── mcp_approval_response ──────────►│
│ │ │ │
│ │ │ ◄────── tool result + response ────────┤
│ │ │ │
│ │ ◄─── 200 OK ────────────────┤ │
│ │ (final response) │ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
```
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add a language identifier to the ASCII diagram code fence.

This fenced block is unlabeled and will trigger markdown lint in stricter setups.

Suggested fix
-```
+```text
 ┌──────────────────────────────────────────────────────────────────────────────┐
 │                              Request Flow                                    │
 ...
 └──────────────────────────────────────────────────────────────────────────────┘
</details>

<!-- suggestion_start -->

<details>
<summary>📝 Committable suggestion</summary>

> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

```suggestion

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/design/human-in-the-loop/human-in-the-loop.md` around lines 72 - 105,
The ASCII diagram code fence in the human-in-the-loop doc is unlabeled and
triggers markdown lint; update the fenced block around the Request Flow diagram
in human-in-the-loop.md by adding a language identifier (e.g., ```text) to the
opening fence so the diagram is treated as plain text and linting passes,
leaving the content unchanged.

@tisnik
Copy link
Copy Markdown
Contributor

tisnik commented Apr 7, 2026

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 1 🔵⚪⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ No major issues detected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants