GitHub
Concept

Requests

Intake funnel for feature requests, clarifications, support questions, and bug reports — with internal/client comment visibility, accept/reject triage, and one-click conversion to issues.

Requests are ProxifAI’s intake funnel. Where tickets handle ongoing customer-support threads with SLAs, requests are short-form intake — “we’d like feature X”, “can you clarify Y?”, “we hit bug Z” — that triage either accepts (often converting to a linked issue) or rejects with a note. They also work as the internal feedback channel: anyone in the org can file a request without bypassing the project planning process.

How requests differ from tickets and issues

QuestionIssuesTicketsRequests
Who creates them?Internal team membersExternal customers via web/email/portal/apiInternal team members or clients (the source field flags which)
What’s the workflow?6-state engineering pipeline (backlogdone)5-state support thread (openclosed) with SLA5-state intake (newaccepted/rejectedcompleted)
Does it carry an SLA?NoYesNo
Can it spawn an issue?Yes (convert action)Yes (auto-fills the LinkedIssue when status flips to accepted)
Comment privacy?All comments are org-visiblePublic messages + internal notesInternal comments + client-visible comments (per-comment toggle)

Anatomy of a request

FieldNotes
titleOne-line summary; required
descriptionLong-form Markdown
typefeature / clarification / support / bug
sourceinternal (team member submitted) or client (came from a client portal/form)
statusOne of 5 values — see Status
prioritylow / medium / high / urgent
requester, requesterInitialDisplay name + initial — works even if the requester isn’t a ProxifAI user
teamIdOptional — scope to one team
clientIdOptional FK to a Client row (the CRM primitive)
linkedIssueIdOptional FK to an Issue — set when triage accepts the request and converts it

Status

Five values from RequestStatus. The flow is intake-driven:

StatusMeaning
newJust submitted; not yet triaged
in_reviewTriage is looking at it — gathering context, asking for more info
acceptedTriage said yes; usually a linked issue is created at this point and the request stays around as the source-of-record
rejectedTriage declined; reason goes in a comment
completedThe request was followed through (either via the linked issue shipping, or because triage acted on it directly)

accepted and completed are kept distinct so dashboards can answer two different questions: “what did we say yes to?” vs “what did we actually ship in response?”

Comment visibility

Every RequestComment has a visibility flag with two values:

  • internal — only visible to org members. Use for “this overlaps with @alice’s work, defer”, “ping @triage-agent to categorize”, etc.
  • client — visible to the client (when the request came from one) on whatever surface they submitted from.

This lets the triage discussion happen privately while still leaving room for direct dialogue with the requester. The same RequestComment.visibility = client you set on a thread you can read back from a client portal.

CLI

pfai request is a thin wrapper over the REST surface — every subcommand follows kubectl-style verbs (list/ls, view/get, delete/rm):

pfai request list                              # list requests in the current org
pfai request list --status new --type bug      # filter
pfai request view <id>                         # full request including comments
pfai request create --title "Add SAML SSO" --type feature --priority high
pfai request update <id> --status accepted --linked-issue eng-204
pfai request stats                             # aggregate counts (per-status, per-type, per-source)
pfai request comments <id>                     # list comments on a request
pfai request comment <id> --content "Approved — see ENG-204" --visibility client
pfai request delete <id>

REST endpoints

Method · PathPurpose
GET /api/v1/requestsList with filters (status, type, source, priority, clientId, teamId)
POST /api/v1/requestsCreate — minimum is {title, type}; everything else has defaults
GET /api/v1/requests/statsAggregate counts for dashboards
GET /api/v1/requests/{id}Read with embedded client, comments
PATCH /api/v1/requests/{id}Update fields (status transitions, priority changes, linked-issue assignment)
DELETE /api/v1/requests/{id}Soft-delete
GET /api/v1/requests/{id}/commentsComment thread
POST /api/v1/requests/{id}/commentsAdd a comment — pass visibility: "internal" or "client"
PATCH /api/v1/requests/{id}/comments/{commentId}Edit your own comment
DELETE /api/v1/requests/{id}/comments/{commentId}Delete your own comment

Triage workflow

A typical request lifecycle:

  1. Submit. Internal user runs pfai request create, or a client posts via the portal — request lands as new.
  2. Pick up. A team-lead or triage agent moves it to in_review and asks clarifying questions in client-visible comments.
  3. Decide. Triage flips to accepted (creating an issue and setting linkedIssueId) or rejected (with a note explaining why).
  4. Track. Accepted requests stay in the system; their linkedIssueId lets dashboards roll up “what we said yes to” vs “what we shipped.”
  5. Close. Once the linked issue ships (or the requestor’s clarification was answered), the request flips to completed.

Trigger rules can automate the easy paths — e.g. a request.created event that auto-tags by category, or auto-rejects requests from blocked clients.

See also