Skip to content

Add issue triage agentic workflow#4

Merged
friggeri merged 1 commit intomainfrom
frg/create-triage-agent
Jan 14, 2026
Merged

Add issue triage agentic workflow#4
friggeri merged 1 commit intomainfrom
frg/create-triage-agent

Conversation

@friggeri
Copy link
Copy Markdown
Collaborator

This workflow automatically triages newly opened issues by:

  • Adding appropriate labels (SDK, type, priority, area)
  • Posting acknowledgment comments
  • Requesting clarification when issues lack detail
  • Detecting and closing duplicate issues

Supports manual triggering via workflow_dispatch with an issue_number input.

This workflow automatically triages newly opened issues by:
- Adding appropriate labels (SDK, type, priority, area)
- Posting acknowledgment comments
- Requesting clarification when issues lack detail
- Detecting and closing duplicate issues

Supports manual triggering via workflow_dispatch with an issue_number input.
@friggeri friggeri requested a review from a team as a code owner January 14, 2026 21:58
Copilot AI review requested due to automatic review settings January 14, 2026 21:58
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an automated issue triage workflow that uses an AI agent to process newly opened issues. The workflow analyzes issues and aims to add labels, post acknowledgment comments, request clarification when needed, and detect/close duplicates.

Changes:

  • Adds a new agentic workflow definition file (issue-triage.md) with AI agent instructions
  • Includes the auto-generated compiled workflow file (issue-triage.lock.yml) for GitHub Actions

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

File Description
.github/workflows/issue-triage.md Workflow definition with AI agent prompt and instructions for triaging issues
.github/workflows/issue-triage.lock.yml Auto-generated GitHub Actions workflow file compiled from the .md definition
Comments suppressed due to low confidence (3)

.github/workflows/issue-triage.md:15

  • The top-level workflow permissions are read-only, which is correct for the agent job. However, the workflow's primary task is to add labels and modify issues, which would require issues: write permission. This aligns with the safe_outputs job which does have issues: write (line 1108 of .lock.yml), but the GitHub MCP server used by the agent is configured as read-only. Consider documenting this design choice or adjusting permissions if label addition is to be implemented.
permissions:
  contents: read
  issues: read
  pull-requests: read

.github/workflows/issue-triage.md:1

  • The concurrency group references github.event.issue.number, which will be undefined when the workflow is triggered via workflow_dispatch. This could cause multiple manual workflow runs to conflict or run simultaneously when they should be serialized. Consider using github.event.issue.number || inputs.issue_number to handle both trigger types properly.
---

.github/workflows/issue-triage.md:72

  • The acknowledgment guideline instructs the agent to mention which labels were applied, but since no labeling capability exists, this will result in misleading comments. The agent would need to either report the missing label tool or provide acknowledgment without mentioning labels. Update the guidelines to reflect the actual available capabilities.
1. **Labeling**: Always apply at least one type label. Apply SDK labels when the issue clearly relates to specific language implementations. Use `needs-info` when the issue is unclear or missing reproduction steps.

2. **Acknowledgment**: Post a friendly comment thanking the author for opening the issue. Mention which labels you applied and why.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


When a new issue is opened, analyze it and perform the following actions:

1. **Add appropriate labels** based on the issue content
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The workflow instructs the AI agent to add labels to issues, but no tool is available to perform this action. The safe-outputs section only defines add-comment, update-issue, and close-issue tools, none of which support adding labels. The GitHub MCP server is also configured with GITHUB_READ_ONLY=1 (line 405 of .lock.yml), preventing write operations. Either add a label management tool to safe-outputs or remove the labeling instructions from the prompt.

This issue also appears in the following locations of the same file:

  • line 12
  • line 70

Copilot uses AI. Check for mistakes.
"-e",
"GITHUB_PERSONAL_ACCESS_TOKEN",
"-e",
"GITHUB_READ_ONLY=1",
Copy link

Copilot AI Jan 14, 2026

Choose a reason for hiding this comment

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

The GitHub MCP server is configured in read-only mode, which prevents the agent from making any write operations including adding labels or modifying issues. This conflicts with the workflow's stated purpose of 'labeling, acknowledging, requesting clarification, and closing duplicates.' The safe-outputs tools (add_comment, update_issue, close_issue) will handle writes, but the agent cannot use the GitHub MCP server to add labels. Either enable write mode or clarify that labeling must be done through an alternative mechanism.

Suggested change
"GITHUB_READ_ONLY=1",
"GITHUB_READ_ONLY=0",

Copilot uses AI. Check for mistakes.
@friggeri friggeri added this pull request to the merge queue Jan 14, 2026
Merged via the queue into main with commit d24f2a2 Jan 14, 2026
28 checks passed
tclem added a commit that referenced this pull request Apr 30, 2026
Closes RFD-400 review findings #1 (writer mutex desync hazard) and #4
(send_request pending-entry leak on cancellation). See cancel-safety
review session db4b1ac8-... for the full report.

The previous design held a `tokio::sync::Mutex<Box<dyn AsyncWrite>>`
across `write_all` + `flush` for Content-Length-framed JSON-RPC
messages. Caller cancellation mid-frame (e.g. wrapping `Session::send`
or `Client::call` in `tokio::time::timeout` or `select!`) could leave
a partial frame on the wire, permanently desyncing the transport for
the rest of the connection. The reader on the CLI side would block
forever waiting for the missing bytes, and the next outbound message
would be interpreted as the tail of the previous body.

Fix: writer-actor task fed by an `mpsc::UnboundedSender<WriteCommand>`.
Public `write` and `send_request` pre-serialize the body, enqueue the
frame + an ack `oneshot`, and await the ack. Caller cancellation
drops the ack receiver but the actor still completes the in-flight
write — the frame either lands atomically or surfaces an io::Error
to the (possibly already-dropped) ack receiver. A partial frame can
never appear on the wire.

Design notes:

- Pre-serialize before enqueue: actor receives `Vec<u8>` (header +
  body, already concatenated). Serde errors fail synchronously at
  enqueue time before touching the actor — cleanest cancel-safety
  story.
- Unbounded sender: RFD 400 explicitly permits this for cancel-safety,
  and the producer-consumer ratio is naturally bounded by request/
  response semantics on the wire.
- Writer actor lives until the JsonRpcClient drops. Channel closes on
  Drop -> actor sees recv None -> flushes and exits.

`pending_requests` cleanup (#4): added a small `PendingGuard` RAII
helper in `send_request` that arms after the map insert and disarms
before the success return. Caller cancellation drops the guard, which
removes the pending-entry synchronously via parking_lot::RwLock (the
map mutex is converted in this commit too — it was never held across
.await anyway, so the conversion is a pure cleanup).

Mutex conversions in this commit:

- `JsonRpcClient::pending_requests`: `tokio::sync::RwLock` ->
  `parking_lot::RwLock`. Lock is never held across .await; conversion
  is also what enables the synchronous PendingGuard drop.
- The previous `Arc<Mutex<Box<dyn AsyncWrite>>>` is gone entirely.
  The actor task owns the writer directly with no shared synchronization.

Tests: two new regression tests in tests/jsonrpc_test.rs

- `write_actor_completes_on_caller_cancel`: tiny duplex (8 bytes) +
  gated reader so the actor's write_all blocks waiting for room. Race
  the caller's future against a sleep; sleep wins, future is dropped
  while suspended on ack_rx.await. Then enqueue a second write and
  release the reader. Both frames must land on the wire intact, in
  order, with no partial frame from the cancelled write.
- `send_request_cancellation_does_not_leak_pending`: cancel an
  in-flight request, then send a (late) response for the cancelled id
  to verify the read loop logs and discards it without colliding,
  then send a fresh request and verify it works normally.

Existing 209 tests continue to pass without modification — the wire
semantics are unchanged. Total now 211.

Validation: cargo test, cargo doc -D warnings, cargo +nightly fmt
--check, cargo clippy --all-features --all-targets -- -D warnings
all clean.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants