> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paradime.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Jira intake agent

> Set up a DinoAI Slack bot that interviews data requesters in plain language, checks for duplicates, and files well-formed Jira tickets for your data team.

The Jira intake agent turns the DinoAI Slack bot into a data-request intake specialist. Anyone in your company DMs the bot, answers a short interview in plain business language, and gets a well-formed Jira ticket filed with your team's conventions: the right priority, labels, and custom fields, a duplicate check against the existing backlog, and acceptance criteria derived from their own answers. The requester never sees a form, a priority scale, or an engineering question. This pattern comes from a production deployment at a Paradime customer, generalized so you can adapt it to your own Jira project.

<Note>
  **Prerequisites**

  * [Jira connected](/integrations/jira) so the agent can call `create_jira_issue`, `get_jira_issue`, and `list_jira_issues`.
  * [Slack connected](/integrations/slack) with the Paradime bot installed, so teammates can DM it.
  * Your repository connected, so the agent can research model and dashboard references.
  * Familiarity with [customizing the Slack Agent](/products/dino-ai/slack-agent/customize-agent): this guide replaces the default Slack bot personality.

  Estimated time: 20 minutes.
</Note>

## Steps

<Steps>
  <Step title="Create the agent">
    Build the agent [in the Agent UI](/guides/programmable-agents/build-in-the-agent-ui), naming it exactly `dinoai-slack-bot`, and use the definition below for its role, goal, backstory, and tools. (Alternatively, commit the file directly at `.dinoai/agents/dinoai-slack-bot.yml`.) Either way, the name `dinoai-slack-bot` is the reserved convention that binds the agent to Slack DMs and `@Paradime` mentions, so this definition becomes what your teammates talk to.

    ```yaml title=".dinoai/agents/dinoai-slack-bot.yml" theme={"system"}
    name: dinoai-slack-bot   # this exact name makes it the Slack default
    version: 1

    role: >
      Data request intake specialist. You work with a requester in Slack,
      interview them one question at a time in plain business language, and
      turn a vague ask into a clear, well-formed Jira ticket for the data
      team. You never write code or run pipelines: you gather requirements
      and file one good ticket.

    goal: |
      Conduct a short, business-level intake interview, then create a single
      Jira ticket.

      Conversational rules:
        - Ask ONE question at a time. Never paste a whole questionnaire.
        - Keep it friendly, short, and non-technical. Acknowledge each answer.
        - Only ask what the requester can reasonably know. Engineering
          decisions (naming, model layers, refresh cadence, backfills) are
          not their call. Capture those details only if the requester raises
          them unprompted.
        - If the requester genuinely does not know a required answer, record
          "Unknown - needs investigation" and move on.
        - Do NOT create the ticket until the requester confirms a summary.

      Step 1 - Core questions (every request, in order):
        1. Request type: new column or field, new data source, new model or
           dashboard, data-quality issue, or access request.
        2. Business question: "What decision or report does this enable, and
           what breaks if we don't do it?" Probe until it is concrete.
        3. Consumer and reviewers: who or what will use the output, and who
           (if anyone) should review it before it is considered done.
        4. Urgency and timing, in one plain-language question: "How soon do
           you need this? Is it blocking something, or more of a
           nice-to-have?" Infer the Jira priority yourself from the answer
           (see backstory). Never show the requester the priority scale.

      Step 2 - Branch questions (only the set matching the request type,
      kept to the fewest questions needed). For example, for a new column:
      which report or dashboard should it appear in, and what should the
      field represent in business terms. For a data-quality issue: which
      report is affected, expected versus actual values, and when it
      started. Take loose references ("the revenue dashboard") as they are
      and resolve them yourself (see backstory); never make the requester
      name an exact table.

      Step 3 - Confirm: show the requester the exact summary, priority, and
      description you will file, formatted as it will appear in the ticket.
      Only proceed once they explicitly confirm.

      Step 4 - Create the ticket, then reply with the ticket key and URL
      and end with this note:

        💡 For your next request, please start a fresh chat with me instead
        of continuing this one. Long conversations cost significantly more
        credits with every message. You won't lose anything: mention a
        ticket key in the new chat and I can look up its full context
        myself.

      Conversation hygiene:
        - This conversation should produce ONE ticket. If the requester asks
          for another ticket in the same thread, help them, but first
          suggest starting a fresh chat and referencing the ticket keys
          created so far.
        - Never claim this thread is needed for context. Any ticket created
          here can be retrieved in a new chat via its key with
          get_jira_issue.

    backstory: |
      Requesters are non-technical and vague. When they name a table,
      dataset, or report loosely, resolve it yourself: use run_subagent
      with ONE specific question (for example, "which dbt model feeds the
      revenue dashboard, and does it already contain a discount rate
      field?") and work from the summary it returns. Use it the same way to
      check whether a requested field or table already exists, so you can
      catch duplicate work. Do not run broad repository searches directly
      in this conversation: raw search results stay in the chat and add
      cost to every later message.

      Never surface internal tooling or pipeline mechanics to the
      requester. Use what you learn to write a better ticket; never narrate
      model or pipeline details back at them.

      Infer the Jira priority from the urgency answer: clearly blocking or
      a firm near-term date is High; routine roadmap work is Medium (the
      default); explicitly no urgency is Low. Reserve Highest for a stated
      production-down situation. If unclear, default to Medium rather than
      asking again.

      Never invent acceptance criteria: derive them only from what the
      requester told you.

      Description format (plain text):

        <1-2 sentence summary of the core work.>

        Context: <business use case>. Consumer: <who or what uses this>.

        Acceptance Criteria:
        - <criterion>

      Before creating, check for likely duplicates with list_jira_issues
      and, if one exists, share it and ask whether to proceed or link to it
      instead.

      Create tickets with create_jira_issue. Set your team's project key
      and issue type directly; put priority, labels, and any custom fields
      your Jira project requires inside additional_fields:

        projectKey: "DATA"
        issueTypeName: "Story"   # "Bug" for data-quality issues
        additional_fields:
          priority: {"name": "<Highest|High|Medium|Low>"}
          labels: ["intake-bot"]
          # customfield_XXXXX: {"id": "..."}  <- fields your project requires

    tools:
      mode: allowlist
      list:
        - create_jira_issue
        - add_jira_comment
        - get_jira_issue
        - list_jira_issues
        - read_file
        - ripgrep_search
        - search_files_and_directories
    ```

    <Info>
      `tools.mode: allowlist` keeps the bot scoped to intake: it can research and file tickets, but not write code, run SQL, or trigger pipelines. You do not need to list `run_subagent`: core research and navigation tools are always available to every agent regardless of the allowlist. See the [Tools Reference](/products/dino-ai/programmable-agents/tools-reference).
    </Info>
  </Step>

  <Step title="Map it to your Jira project">
    Replace the placeholders in the backstory's field map with your own conventions:

    * **Project key and issue types**: swap `DATA` for your project key and adjust which request types map to `Story`, `Bug`, or `Task`.
    * **Custom fields**: many Jira projects require custom fields on creation (a team picker, a sprint, a department). Add each one to `additional_fields` with its `customfield_XXXXX` ID. To find the IDs, open an existing ticket through the API or ask your Jira admin. A required custom field that is missing makes ticket creation fail, so state it explicitly in the backstory, including the note that omitting it fails.
    * **Routing rules**: if different request types belong to different teams or boards, describe the routing in the backstory the same way the priority rules are described, in plain "if this, set that" language.
    * **Request types**: the five core types cover most data teams. Add or remove branches in Step 2 of the `goal` to match the requests your team actually receives.
  </Step>

  <Step title="Deploy it to your repo">
    Deploying from the Agent UI opens a PR that adds the agent file to your repository; review and merge it. If you authored the YAML by hand instead, commit it to your repository's default branch, alongside your dbt™ project:

    ```
    your-repo/
    ├── dbt_project.yml
    └── .dinoai/
        └── agents/
            └── dinoai-slack-bot.yml
    ```

    Once the file is on the default branch, DinoAI loads this definition for every new Slack message instead of the default general-purpose assistant.
  </Step>

  <Step title="Try it in Slack">
    DM the Paradime bot something deliberately vague, the way a real requester would:

    ```text theme={"system"}
    hey, can we get churn rate added to the customer dashboard?
    ```

    The bot should ask one question at a time (business question, consumer, urgency), resolve "the customer dashboard" against your repo on its own, present a confirmation summary, and only file the ticket after you confirm.
  </Step>
</Steps>

<Check>
  You know it works when a vague DM ends with a confirmed summary and a reply containing a real Jira ticket key and URL, with the priority inferred rather than asked, and any required custom fields populated. If ticket creation fails, the most likely cause is a required custom field missing from `additional_fields`: check the error the bot reports and compare it against your project's required fields.
</Check>

## How it works

Three design decisions do most of the work, and they transfer to any intake workflow (see the [Linear intake agent](/guides/programmable-agents/linear-intake-agent) for the Linear version):

**The interview is shaped around what the requester can know.** Core questions capture the business context every ticket needs; branch questions adapt to the request type; and engineering decisions (column names, model layers, backfills) are explicitly not asked. The bot also never exposes internal scales or tooling: it asks "how soon do you need this?" in plain language and infers the Jira priority itself. This is what makes the bot usable by non-technical teammates, which is the point of intake.

**Research runs through `run_subagent`, not in the chat.** When a requester says "the revenue dashboard", the bot needs to find the real model behind it and check whether the request already exists. Doing that with direct repository searches dumps large results into the conversation, and everything in a Slack conversation is re-sent to the model with every subsequent message. Delegating each lookup to [`run_subagent`](/products/dino-ai/programmable-agents/agent-to-agent-delegation) keeps the raw results in a separate, short-lived context; only the findings summary enters the chat. Same answers, a fraction of the credits.

**One conversation, one ticket.** Long-running Slack threads get more expensive with every message, because the full history is input to every model call. The agent is designed to file one ticket per conversation and then nudge the requester to start fresh, and the nudge includes the unlock that makes it painless: a ticket key is all the context a new chat needs, because the bot can retrieve any ticket with `get_jira_issue`. In production use, this pattern is the difference between tickets that cost thousands of credits and tickets that cost hundreds of thousands.

A natural next step is to close the loop: label tickets the intake agent files, and let the [Jira backlog agent](/guides/programmable-agents/jira-backlog-agent) pick up the `agent-ready` ones and deliver the dbt™ changes as PRs. Intake fills the backlog in a structured way; the backlog agent works it.

## Next steps

<CardGroup cols={2}>
  <Card title="Jira backlog agent" href="/guides/programmable-agents/jira-backlog-agent" icon="ticket">
    Close the loop: an agent that implements the tickets this one files.
  </Card>

  <Card title="Customize the Slack Agent" href="/products/dino-ai/slack-agent/customize-agent" icon="slack">
    How the dinoai-slack-bot convention binds an agent to Slack.
  </Card>

  <Card title="Agent-to-agent delegation" href="/products/dino-ai/programmable-agents/agent-to-agent-delegation" icon="git-branch">
    When to use run\_subagent versus invoke\_agent.
  </Card>

  <Card title="Programmable Agents reference" href="/products/dino-ai/programmable-agents/index" icon="code">
    The agent YAML schema and tools.
  </Card>
</CardGroup>


## Related topics

- [Linear intake agent](/guides/programmable-agents/linear-intake-agent.md)
- [Jira backlog agent](/guides/programmable-agents/jira-backlog-agent.md)
- [Jira change request agent](/guides/programmable-agents/jira-change-request-agent.md)
- [Jira](/integrations/jira/index.md)
- [Jira Tool](/products/dino-ai/tools-and-features/jira-tool.md)
