agent channels · kagent A2A · agentgateway models
Interactive multi-agent Telegram and a pure-GitOps agent scheduler share the same kagent fleet. Every model call still goes through Solo Enterprise AgentGateway — traced, priced, and key-injected upstream. Git remains the source of truth; the cluster only executes.
Channels at a glance
Both channels speak A2A to in-cluster agent Services. Neither holds provider API keys — kagent ModelConfigs point at agentgateway, and the gateway injects real upstream credentials from Vault-synced Secrets.
You message the bot; it polls Telegram, routes to the selected agent over A2A, and streams the reply (with HITL Approve/Reject when tools require approval).
Save a schedule in the web UI → GitHub PR auto-merges → Argo applies a CronJob → Job POSTs A2A → results land in ConfigMaps (and optionally Telegram).
config/agent-schedules/ags-result-* ± TelegramReference path
Telegram and the scheduler are edge adapters. The agents, tools, and LLM hops are the same stack documented on the platform page — kagent runtime, MCP tool servers, AgentGateway backends.
Interactive channel
Same pattern as the k8s-iceman bot, adapted for goose: one polling Deployment, a JSON map of agent aliases to in-cluster A2A URLs, and HITL buttons when an agent needs approval.
Open @KagentCorpAIbot — private chat or group where the bot is invited.
telegram-bot pod long-polls Telegram; token from Vault via ExternalSecret.
JSON-RPC message/send to http://<agent>.kagent:8080/ with session continuity.
Agent answer returns as chat text. Destructive tools surface Approve / Reject inline buttons.
| Command | Action |
|---|---|
/start | Help |
/agents | List aliases + A2A URLs |
/use <alias> [msg] | Switch agent; optional message in same turn |
/new | Reset session |
/status | Ping current agent |
@forti … | Switch + message in one line |
| Alias | Service |
|---|---|
k8s | k8s-agent (default) |
forti | fortigate-agent |
f5 | f5-bigip-agent |
github | github-agent |
drone | drone-agent |
demo | demo-agent |
telegram-bot/ — source + Dockerfileconfig/telegram-bot/ — Deployment + ExternalSecretdocs/telegram-bot.md — operator notesagentgateway/telegramapi_key → BotFather tokenchat_id → numeric id for schedule notifiestelegram-bot-token (ns kagent)@sebbycorp only/status after /useUnattended channel
The UI never creates CronJobs as desired state via the Kubernetes API. It only opens a pull request on sebbycorp/k8s-goose; ArgoCD applies config/agent-schedules/*.
Name, agent, cron (UTC), prompt, optional Telegram notify. POST /api/schedules.
GitHub REST with PAT from Vault (github/mcp). Auto-merge when allowed.
agentgateway-config syncs → CronJob/ags-<name> in ns kagent.
Job POSTs A2A, writes ConfigMaps, optionally posts to Telegram using the shared bot token.
agent-scheduler/ — FastAPI UI + Dockerfileconfig/agent-scheduler/ — deploy, NodePort 30955, RBAC, ESOconfig/agent-schedules/ — one CronJob YAML per scheduledocs/agent-scheduler.md — full operator guideags-result-<name> — latest (overwrite)ags-hist-<name>-<ts> — history snapshottext, raw.json, status, httpCode, …GET /api/results/…| Method | Path | Description |
|---|---|---|
GET | /healthz | Liveness + GitHub token present |
GET | /api/agents | Live kagent Agents |
GET / POST | /api/schedules | List / upsert via PR |
DELETE | /api/schedules/{name} | Delete via PR |
GET | /api/results[/{name}] | List or load result ConfigMaps |
GET | /api/presets | Cron presets (hourly, daily, …) |
When Send result to Telegram is checked, each Job posts a short summary to TELEGRAM_CHAT_ID using the same Vault bot token as the chat bot. Re-save schedules after enabling so CronJobs pick up the notify step. Message format: schedule name, agent, status, timestamp, and a reply preview.
HITL requireApproval can block unattended cron for destructive tools — start with read-only prompts.
Cron is UTC. Result bodies are truncated for ConfigMap size limits. History ConfigMaps are not auto-pruned.
The UI requests minimal CPU so it still schedules on a tight worker.
Shared foundation
Whether you type in Telegram or a CronJob fires, the agent still calls an OpenAI-compatible base URL that is an in-cluster gateway. Provider keys stay in Vault → ESO → gateway backend Secrets.
| ModelConfig | Model | Gateway baseUrl (in-cluster) |
|---|---|---|
default-model-config |
gpt-4o / lab default | …/openai/v1 · agentgateway-proxy |
xai-grok |
grok-4.5 | …/grok/v1 · xai-grok-gateway |
dgx-spark |
Qwen3.8-27B (NVFP4), local | …/spark/v1 · dgx-spark-gateway |
gpt-5-6 |
gpt-5.6 | …/gpt56/v1 · dedicated gateway |
@k8sOperator runbook
Lab-only: NodePorts are plain HTTP. Confirm the worker IP with kubectl get nodes -o wide if DHCP moved it.
# api_key = BotFather token · chat_id from getUpdates after /start kubectl --context maniak-goose -n vault exec vault-0 -- \ vault kv put agentgateway/telegram \ api_key='' \ chat_id='' kubectl --context maniak-goose -n kagent annotate externalsecret telegram-bot-token \ force-sync=$(date +%s) --overwrite kubectl --context maniak-goose -n kagent get externalsecret telegram-bot-token kubectl --context maniak-goose -n kagent get pods -l app.kubernetes.io/name=telegram-bot
# UI (worker NodePort) open http://172.16.10.155:30955/ kubectl --context maniak-goose get cronjobs -n kagent \ -l app.kubernetes.io/managed-by=agent-scheduler kubectl --context maniak-goose get cm -n kagent \ -l app.kubernetes.io/managed-by=agent-scheduler # one-shot without waiting for cron kubectl --context maniak-goose create job -n kagent \ --from=cronjob/ags-<name> manual-<name>-1 kubectl --context maniak-goose logs -n kagent -f job/manual-<name>-1
# In Telegram: # /start # /agents # /use k8s # /status # ask a read-only question first kubectl --context maniak-goose -n kagent logs \ -l app.kubernetes.io/name=telegram-bot --tail=50
http://172.16.10.155:30955/:30854 (kagent + AgentGateway)maniak-goosesebbycorp/telegram-kagent-bot:goose-0.1.0sebbycorp/agent-scheduler:0.1.3docker buildx … --platform linux/amd64docs/telegram-bot.mddocs/agent-scheduler.mddocs/superpowers/specs/…agent-scheduler-design.md