コンテンツにスキップ

GitHub Copilot

Required secret Overlay
DISCORD_BOT_TOKEN values-github-copilot.yaml

When to use it

A Discord bot, GitHub Copilot access, and persistent storage are required so login tokens can be reused.

Install

helm upgrade --install hermes-agent ./charts/hermes-agent \
  --namespace hermes-agent --create-namespace \
  -f charts/hermes-agent/values-github-copilot.yaml \
  --set-string env.DISCORD_BOT_TOKEN='<real-value>' --wait

When an example requires more than one credential, pass every listed value with --set-string or use extraEnvFrom to reference an existing Secret.

Adapt before deploying

Approve the device code from the initial pod logs or Discord prompt in GitHub.

Open Raw YAML

Complete overlay

charts/hermes-agent/values-github-copilot.yaml
# values-github-copilot.yaml
#
# Hermes Agent backed by GitHub Copilot, authenticated at startup via the OAuth
# 2.0 Device Authorization Grant (RFC 8628): no API key to paste. The
# "auth-device-login" init container surfaces a verification link + code to your
# Discord home channel, waits for you to approve it on github.com (phone is
# fine), then persists the resulting token to HERMES_HOME/.env where Hermes
# reads it natively. The token lives on the persistent volume, so restarts are
# fast; re-login only happens when it is missing or revoked.
#
# Copilot's token API rejects PATs: a device-flow `gho_`/`ghu_` token is
# required, which is exactly what this flow produces.
#
# All secrets below are DUMMY placeholders. Do NOT commit real keys: override
# them at install time (--set-string) or inject via a SealedSecret + extraEnvFrom
# (see examples/argocd/).
#
#   helm upgrade --install hermes-agent ./charts/hermes-agent \
#     --namespace hermes-agent --create-namespace \
#     -f charts/hermes-agent/values-github-copilot.yaml \
#     --set-string env.DISCORD_BOT_TOKEN='<real-bot-token>' --wait
#
#   # then watch the login init container for the verification prompt:
#   kubectl logs deploy/hermes-agent -n hermes-agent -c auth-device-login -f

config:
  model:
    # Hermes' built-in GitHub Copilot provider (calls the Copilot token API).
    provider: copilot
    # Any model your Copilot subscription can reach. Examples: gpt-4o, gpt-4.1,
    # claude-sonnet-4.5, gemini-2.5-pro, gpt-5.
    default: gpt-4o
  terminal:
    backend: local

# Authenticate the Copilot credential via the OAuth device flow at startup.
auth:
  deviceFlow:
    enabled: true
    provider: github-copilot
    # Deliver the verification link + code to the agent's Discord home channel
    # (reuses DISCORD_BOT_TOKEN + DISCORD_HOME_CHANNEL). It is always also
    # printed to the init container logs as a fallback.
    notify: discord

env:
  # The chart's default placeholder is for OpenAI; this deployment doesn't use
  # it (the Copilot token is fetched at runtime via device flow). Set to a clear
  # sentinel so no real OpenAI key is implied.
  OPENAI_API_KEY: "unused"

  # --- Discord bot (secret bits) ------------------------------------------
  # Setting the token is enough to auto-enable Discord: no config.yaml change.
  # The login init container reuses this same bot to post the verification link.
  # Create the bot at https://discord.com/developers/applications, enable the
  # "Message Content Intent", and invite it to your server.
  DISCORD_BOT_TOKEN: "MTA0DUMMYtoken000000000000.DUMMY.replace_me_with_a_real_token"

# Non-secret Discord knobs go here (plain env, not the Secret). The login init
# container also reads DISCORD_HOME_CHANNEL from here to know where to post.
extraEnv:
  - name: DISCORD_HOME_CHANNEL        # channel id for cron / notification / login delivery
    value: "000000000000000000"       # DUMMY - your channel id (18 digits)
  - name: DISCORD_ALLOWED_USERS       # comma-separated user ids allowed to talk
    value: "111111111111111111"       # DUMMY - your Discord user id
  - name: DISCORD_ALLOW_ALL_USERS     # true only for throwaway/dev bots
    value: "false"

# Persistence is required for device-flow login: the token is written here so it
# survives restarts (otherwise you would re-approve on every restart). Empty
# storageClass = cluster default; on a Raspberry Pi cluster that is typically
# local-path (k3s) or microk8s-hostpath: both ReadWriteOnce, which is exactly
# what this single-writer workload wants.
persistence:
  enabled: true
  storageClass: ""
  accessModes:
    - ReadWriteOnce
  size: 5Gi

# Defaults are already tuned for small arm64 nodes; shown here for visibility.
resources:
  requests:
    cpu: 100m
    memory: 256Mi
  limits:
    cpu: "1"
    memory: 1Gi