Skip to content
Scalekit Docs
Talk to an Engineer Dashboard

Triage a Gmail inbox with AgentKit and the LiteLLM gateway

Node.js inbox triage agent: classify Gmail threads, route to GitHub repos, draft issues and replies via LiteLLM, and approve before any side effects.

Build an automated inbox triage agent that reads your Gmail, classifies each thread, routes it to the right GitHub repository, and notifies Slack — then waits for your approval before creating issues or sending replies. This Node.js sample uses Scalekit AgentKit for OAuth tool execution (Gmail, GitHub, Slack) and a LiteLLM gateway for model-per-stage routing. The only LiteLLM-specific config is LITELLM_BASE_URL and a virtual API key from the dashboard.

The sample repository is litellm-agentkit-inbox-triage on GitHub.

  • Gmail ingestion — Poll for new threads using AgentKit-executed Gmail tools. A SQLite cursor prevents duplicate processing.
  • Model-per-stage routing — Each stage (classify, research, tiebreak, draft) calls the LiteLLM gateway with a different model name. Stage-to-model assignments live in routing.yaml at the repo root.
  • Deterministic GitHub routing — Keyword rules in routing.yaml pick a target repository; an optional LLM tie-breaker resolves ties.
  • Research loop — A small tool-calling loop searches related GitHub issues through AgentKit.
  • Slack notification — Posts a summary with a link to the pending decision.
  • Human approval — A localhost dashboard lists proposals. Approve creates the GitHub issue, sends the Gmail reply, and updates Slack. Reject discards without side effects.

New Gmail threads flow through AgentKit into a multi-stage LiteLLM pipeline, then land in SQLite as pending proposals.

Gmail inboxIngest(AgentKit)LiteLLM pipelineStore(SQLite)ClassifyRoute(routing.yaml)Research(AgentKit)Draft

Proposals wait in SQLite until you review them from the dashboard.

Pending proposal(SQLite)Notify Slack(AgentKit)Dashboard(localhost:3000)ApproveReject(no side effects)Create issue+ send reply(AgentKit) approve reject
  • A Scalekit account at app.scalekit.com.
  • Ability to create AgentKit connections for Gmail, GitHub, and Slack. Connection names must match what you put in .env (see Configure a connection).
  • A virtual LiteLLM API key from the dashboard (LLM Gateway). A small spend cap of roughly two US dollars covers a handful of test threads.
  • Node.js 24 or newer and npm.
  • An interactive terminal — the sample prints authorization links and waits for Enter after each connector. This recipe does not cover headless CI.
  1. Terminal window
    git clone https://github.com/scalekit-developers/litellm-agentkit-inbox-triage.git
    cd litellm-agentkit-inbox-triage
    1. Open app.scalekit.comAgentKitConnectionsCreate Connection for Gmail, GitHub, and Slack.
    2. Copy each Connection name exactly as shown in the dashboard into GMAIL_CONNECTION_NAME, GITHUB_CONNECTION_NAME, and SLACK_CONNECTION_NAME in your .env file.
    3. For GitHub, confirm the connection includes the repo OAuth scope (needed to create issues and search across repositories). Check AgentKit → Connections → GitHub → Scopes in the dashboard. See Scopes and permissions and the GitHub connector.
    4. For Gmail and Slack, follow the dashboard wizard. If your workspace restricts OAuth apps, see the connector docs: Gmail, Slack.
  2. Create a LiteLLM virtual key and verify the gateway

    Section titled “Create a LiteLLM virtual key and verify the gateway”

    Open LLM Gateway in the Scalekit dashboard and create a virtual API key (optionally set a small budget cap for evaluation).

    Verify the gateway responds before continuing (load your .env first with set -a && source .env && set +a):

    Terminal window
    curl -H "Authorization: Bearer $LITELLM_API_KEY" \
    "$LITELLM_BASE_URL/v1/models"

    Align routing.yamlmodels: with the model IDs returned by that endpoint.

  3. Set these variables in .env before running:

    VariableWhere to find it
    SCALEKIT_ENV_URLDashboard → Settings → Environment URL
    SCALEKIT_CLIENT_IDDashboard → API Credentials
    SCALEKIT_CLIENT_SECRETDashboard → API Credentials
    GMAIL_CONNECTION_NAMEDashboard → AgentKit → Connections (exact label)
    GITHUB_CONNECTION_NAMESame
    SLACK_CONNECTION_NAMESame
    LITELLM_BASE_URLDashboard → LLM Gateway → Base URL
    LITELLM_API_KEYDashboard → LLM Gateway → virtual key value
    Terminal window
    cp .env.example .env
    # Fill in the variables above
    npm install
    npm run dev

    Complete each printed authorization URL in the browser, then press Enter in the terminal after each connector.

    When you see All connectors active and dashboard listening on http://localhost:3000, send a test email to the connected Gmail account. Within roughly one poll interval (default 5 seconds), a proposal appears in the dashboard.

  4. Open http://localhost:3000. Review the classification, routed repository, related issues, and drafts. Approve runs GitHub issue creation, sends the Gmail reply, and updates Slack. Reject leaves external systems unchanged.

  5. To add routing targets or swap models per stage, edit routing.yaml — each entry maps keyword rules to a GitHub repository and assigns a model name to each pipeline stage. To add connectors, follow the AgentKit connections guide and add the new connection name to .env.

TopicLink
AgentKit overviewOverview
ConnectionsConfigure a connection
Authorization linksAuthorize a user
Connected accountsManage connected accounts
LiteLLM virtual keysVirtual keys
LiteLLM model routingRouter
LiteLLM OpenAI-compatible APIProxy usage
Why am I seeing random tool failures or connection not found errors?

The *_CONNECTION_NAME variables in .env must match the connection labels exactly as shown in the dashboard — including capitalization and spacing.

Solution: Open AgentKit → Connections in the dashboard, copy each connection name exactly, and paste it into GMAIL_CONNECTION_NAME, GITHUB_CONNECTION_NAME, and SLACK_CONNECTION_NAME.

Why is GitHub returning a 403 or permission error?

The GitHub AgentKit connection is missing the repo OAuth scope, which is required to create issues and search across repositories.

Solution: In the dashboard, go to AgentKit → Connections → GitHub → Scopes and confirm repo is included. Re-authorize the connection if you need to add it.

Why am I seeing unknown model errors from LiteLLM?

A model name in routing.yaml is not available on your LiteLLM gateway instance.

Solution: Run the following to list available models, then update routing.yamlmodels: to match:

Terminal window
curl -H "Authorization: Bearer $LITELLM_API_KEY" \
"$LITELLM_BASE_URL/v1/models"
Why isn’t the dashboard loading at localhost:3000?

The sample binds the dashboard only after all three connectors finish authorization. If any connector step was skipped or the terminal is still waiting for Enter, the dashboard won’t start.

Solution: Check the terminal output — the sample prints an authorization URL for each connector and waits for you to press Enter after completing it in the browser.

For deeper debugging patterns, see Authentication troubleshooting.