All articles

Slash commands as a product primitive: /jira, /email, /servicenow from the home screen and why they beat deep links

Suman Akkisetty
Founder, KaryoSpace
April 2026
9 min read

Deep links feel clever until a user asks "how do I create a Jira ticket from here?" The answer is a URL with six query parameters, two of which need to be URL-encoded. Nobody remembers that. Nobody should have to.

Slash commands are the alternative. Type /jira on the home screen, select a project, add a title, press enter. The ticket is created. The same interaction for ServiceNow, for email, for calendar events. This article covers how slash commands work in KaryoSpace and why they are wired into the KRE audit trail.

The handlers

// home_action_handlers.go — Handlers that power the /jira, /confluence, /servicenow
// slash commands on the Home screen.
//
//   GET  /integrations/jira/projects     — list Jira projects for dropdown
//   POST /integrations/jira/create       — create a Jira issue
//   POST /integrations/servicenow/create — create a ServiceNow incident

Three routes, three functions, no routing magic. Each slash command maps directly to an integration handler on the IntegrationHandlers struct.

Jira slash command

func (h *IntegrationHandlers) JiraListProjects(w http.ResponseWriter, r *http.Request) {
    // GET /integrations/jira/projects
    // Returns []JiraProject{Key, Name} for the org's connected Jira instance
    // Used to populate the project dropdown in the /jira UI
}

func (h *IntegrationHandlers) JiraCreateIssue(w http.ResponseWriter, r *http.Request) {
    // POST /integrations/jira/create
    // Body: {project_key, issue_type, summary, description}
    // Creates the issue, then:
    queryText := fmt.Sprintf("/jira create %s %s: %s",
        body.ProjectKey, body.IssueType, body.Summary)
    h.storeUserQuery(userID, queryText, result, traceID, sources, scope)
}

The storeUserQuery call at the end is not logging for its own sake. It feeds the KRE pipeline. When a user types /jira but cannot find the right project, that failed interaction shows up in the gap analysis. KRE identifies it as a knowledge gap: "users are looking for a Jira project that does not exist in the connected instance."

ServiceNow slash command

func (h *IntegrationHandlers) ServiceNowCreateIncident(w http.ResponseWriter, r *http.Request) {
    // POST /integrations/servicenow/create
    // Dual-write: creates incident in ServiceNow AND in internal incident store
    // Returns both internal ticket_id (INC-2026042) and ServiceNow sys_id
}

The dual-write is intentional. If ServiceNow is unavailable, the internal incident still exists and the team can work from KaryoSpace alone. When ServiceNow comes back, the sync worker reconciles the state. This is the same philosophy as the calendar sync: external systems are optional overlays, not hard dependencies.

Email slash command

The email home handlers live in email_home_handlers.go:

Calendar slash command

The calendar module includes a slash command test file at calendar/slash_command_test.go that covers natural language time parsing:

// Examples parsed by the slash command handler
"/meet at 3pm tomorrow for 1 hour"
"/meet next Tuesday 10am with linda@company.com"
"/meet Friday afternoon — 30 minutes"

The parser handles relative times ("tomorrow", "next Tuesday"), absolute times ("3pm", "10am"), and durations ("1 hour", "30 minutes"). It creates an internal event and pushes it to Google Calendar or Outlook if either is connected, using the same ExternalCalendarSync.PushEvent path as any other calendar write.

The command-to-KRE pipeline

1

Parse and validate

Input validated against the expected schema. Unknown project keys, missing required fields, or malformed commands return 400 immediately.

2

Execute the action

Create the Jira issue, send the email, create the ServiceNow incident, or book the calendar event. Return success with the created resource ID.

3

Store the query

Call storeUserQuery(userID, commandText, result, ...). The command text is stored verbatim in user_queries collection for KRE analysis.

4

KRE classifies

The KRE background worker reads user_queries and classifies each entry. Repeated failed commands surface as knowledge gaps in the admin Gaps tab.

CommandRouteWrites toKRE tracked
/jiraPOST /integrations/jira/createJira + user_queriesYes
/servicenowPOST /integrations/servicenow/createServiceNow + incidents + user_queriesYes
/emailPOST /email/sendEmail + audit_log + user_queriesYes
/meetPOST /calendar/api/eventsCalendar + external + user_queriesYes

Why slash commands beat forms

Forms require navigation. The user leaves the home screen, fills a form, submits, returns. Slash commands are inline: one text input, one enter, done. The user stays on the home screen. The action is confirmed in the feed.

The second advantage is machine-readability. A form submission is opaque: the system knows a ticket was created. A slash command stores the full text: /jira create SCRUM Bug: Login fails on mobile. KRE can parse that and understand not just that a ticket was created, but what kind of ticket, in which project, about what topic. That is the signal that closes knowledge gaps.


Slash commands are a small surface that generates a large amount of structured signal. Every command execution is a data point about what users are actually doing, in a format that is parseable by the AI layer. The gap between "a user clicked a button" and "a user typed /jira create SCRUM Bug: Login fails on mobile" is the difference between usage analytics and knowledge analytics.

Get in touch
Message sent