GOOSE · FLIGHT DECK ← platform  ·  KEEPALIVE 5s
CALLSIGN · TELLO@172.16.10.168 · SDK v3

The drone that
answers to prose.

A Ryze RoboMaster TT flown by AI agents — telemetry, flight, and camera spoken as plain English, routed through agentgateway as MCP, and kept live by a five-second heartbeat.

15
MCP tools
4
tool-mode agents
3
UDP channels
5s
keepalive heartbeat
01 · THE AIRCRAFT

A palm-sized quadcopter,
on the lab network.

The bird is a Ryze RoboMaster TT (Tello) in station mode — it joins the lab Wi-Fi at a reserved address and speaks the Tello SDK over three UDP channels. Everything the agents do bottoms out in those datagrams.

🛰️

:8889 command

Flight & query commands in, ACKs back.

takeoff · move · battery?
📡

:8890 state

Telemetry broadcast ~10 Hz while in SDK mode.

bat · height · attitude
🎥

:11111 video

H.264 stream for photos & recording.

take_photo · record
02 · SIGNAL CHAIN

From a sentence to a spinning rotor.

A request crosses four boundaries — model, gateway, MCP server, radio — and the telemetry comes back the same way. The gateway is the one control point: it prices, traces, and shapes every tool call.

🧑‍✈️

You

Plain English in the kagent UI.

"do a flip"
A2A
🤖

Agent · gpt-5.5

Reasons, picks a tool.

kagent · declarative
MCP
🚦

agentgateway

Tool-mode proxy, tracing, budgets.

/drone · :31606
🖥️

drone MCP server

Owns the UDP link · hostNetwork pod · 5s keepalive.

drone-system ns
UDP
🚁

The drone

Executes, streams telemetry back up the chain.

Tello SDK
03 · COMMAND LIFECYCLE

What happens when you ask.

A real trip through the stack — "what's the battery?" — plus the heartbeat that runs the whole time in the background so the answer is never stale.

1

Prompt

You type it (or tap an example). The agent, on gpt-5.5, decides get_battery is the right tool.

2

Through the gateway

The call hits agentgateway at /drone, which routes it to the drone MCP server — and traces it to Langfuse.

3

Onto the radio

The server sends battery? as a UDP datagram to the drone on port 8889 and waits for the reply.

4

Answer returns

The drone replies 76; it flows back up the same chain and the agent says it in plain English.

Meanwhile — the heartbeat

Every 5s the server re-sends command, keeping the drone in SDK mode so telemetry never stops.

Freshness, not fiction

get_state reports connected / stale / state_age_s — a dead link reads false, never a frozen value.

04 · FOUR WAYS TO HOLD THE STICK

One drone, four tool modes.

agentgateway can present the same 15 tools four different ways — from the full list to a single code sandbox — trading model context for directness. Each mode is its own agent and endpoint, all flying the same aircraft.

standard

drone-agent

All 15 tools, exposed directly. The simplest path — the model sees everything.

:31606/droneget_state · takeoff · move · flip · take_photo …
search

drone-agent-search

Two meta-tools. The model looks a tool up, then invokes it — keeps context small.

:31606/drone-searchget_tool · invoke_tool
code

drone-agent-code

One tool: the model writes JavaScript that calls the drone in a 15s sandbox.

:31606/drone-coderun_code
codesearch

drone-agent-codesearch

Discover typed signatures, then write code against them. Smallest footprint of all.

:31606/drone-codesearchget_tool · run_code
05 · TOOL CATALOG

Sixteen tools, five systems.

Every capability the drone MCP server exposes, grouped the way the aircraft is. The agent calls these by name (Standard mode) or discovers them at runtime (Search / Code). Plus two canned prompts — one-tap procedures that orchestrate several tools.

Telemetry 2

  • get_stateLive connected/stale flags + battery, height, attitude, ToF.
  • get_batteryActive battery? query — guaranteed-current %.

Flight 6

  • takeoffAuto lift-off. Refused below 15% battery.
  • landAuto land (retries through Wi-Fi blips).
  • emergencyCut all motors immediately.
  • moveup/down/left/right/forward/back · 20–500 cm.
  • rotatecw / ccw · 1–360°.
  • flipforward / back / left / right.

Camera 5

  • take_photoStill the agent can see and describe.
  • start_recordingBegin an mp4 capture.
  • stop_recordingSave the current recording.
  • list_mediaPhotos & videos on disk.
  • get_mediaFetch a captured photo by name.

LED matrix 2

  • set_led_textScroll text on the 8×8 — color, direction, speed.
  • clear_ledBlank the display.

Raw 1

  • send_commandAny Tello SDK / RMTT EXT command. Advanced.

Prompts canned

  • preflight_checkGuided readiness sweep → a clear GO / CAUTION / NO-GO verdict.
  • orbit_and_photographCircle an object at a set distance and shoot all four sides.
06 · THE SKILL & THE AGENT

What it knows before it flies.

An agent isn't just a model with tools — it carries a skill (an operating runbook) and a brief that shape how it flies. Both live in Git, so every agent behaves the same across restarts.

📖

Skill · drone-operations

A runbook the agent pulls from this repo (skills/drone) at runtime — not baked into the model. It carries the facts a pilot needs: the drone's IP and UDP ports, that takeoff is refused under 15% and <30% means "land soon", how to read stale telemetry, and to describe a photo rather than dump JSON. Edit the runbook, and every agent's behavior updates on the next pull.

🧩

Five ingredients

Each of the four agents is the same recipe with one dial changed — the tool mode. The model, skill, and safety rules stay constant; only how the tools are presented differs. That's what makes them a clean side-by-side comparison.

Model
gpt-5.5
Via agentgateway's OpenAI route — the agent never holds a real key.
Tools
RemoteMCPServer
Points at a /drone* endpoint — the tool mode lives here.
Skill
drone-operations
gitRef runbook, fetched at runtime from this repo.
Brief
systemMessage
Mode-specific: how to use get_tool / run_code, plus flight rules.
Examples
a2aConfig
The tappable prompts — "can you take off", "do a flip".
07 · FLIGHT SYSTEMS

Built for a flaky Wi-Fi world.

The drone drops SDK mode after ~15s of silence and its Wi-Fi is unreliable. Four systems keep the picture honest and the aircraft safe.

💓

Keepalive

A background thread re-sends command every 5 seconds, so telemetry streams non-stop — and a drone you just charged reconnects on its own within ~5s. No pod restart.

🩺

Freshness

get_state stamps every packet. connected means "heard from it in the last 5s" — otherwise stale:true, so the agent never quotes a frozen number.

🔋

Live battery

get_battery actively asks the drone (battery?) instead of trusting the cache — the reading you get is the reading right now.

⚠️

Selective retry

Idempotent commands (battery, land, emergency, keepalive) retry through Wi-Fi blips. Movement never does — a timed-out move may have already run, and a retry would double it.

battery? ↻land ↻move ✗flip ✗
08 · PRE-FLIGHT SETUP

The whole rig, in a few files.

Everything is GitOps — edit, push, ArgoCD syncs. Here's the shape: the server on the drone LAN, a gateway endpoint per mode, and an agent that speaks to it.

drone-mcp-server.yamlhostNetwork · drone-system
# owns the drone's UDP link directly
env:
  - name: TELLO_IP
    value: "172.16.10.168"  # DHCP-reserved
hostNetwork: true
nodeSelector:
  kubernetes.io/hostname: talos-9kw-b68
EnterpriseAgentgatewayBackendtool mode
spec:
  entMcp:
    toolMode: Code  # Standard|Search|Code|CodeSearch
    codeMode: { timeout: "15s" }
    targets:
      - static:
          host: drone-mcp-server.drone-system…
          port: 8090
          path: /mcp/
talk to it — MCP initialize over the gatewaycopy
curl -s http://172.16.10.155:31606/drone \
  -H 'Content-Type: application/json' \
  -H 'Accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize",
      "params":{"protocolVersion":"2025-06-18",
      "capabilities":{},"clientInfo":{"name":"cli","version":"0"}}}'
EndpointURLExposes
Standard172.16.10.155:31606/droneall 15 tools
Search…/drone-searchget_tool · invoke_tool
Code…/drone-coderun_code
CodeSearch…/drone-codesearchget_tool · run_code