Skip to content

[FEATURE] Ship foreman-agent (and metal-agent) via the Homebrew tap for one-command edge upgrades #822

Description

@Defilan

Feature Description

Ship the off-cluster foreman-agent (and ideally the metal-agent) through the existing Homebrew tap (defilantech/homebrew-tap) so edge nodes can be upgraded with brew upgrade instead of the manual download-and-symlink-flip procedure.

Today the goreleaser brews: block only taps the llmkube CLI (it explicitly excludes the agents: "Only include the CLI archive (not Metal agent)"). The agents ship as release tarballs only.

Problem Statement

As an operator of an off-cluster LLMKube fleet (Apple Silicon / edge Macs), I want to upgrade the foreman-agent with brew upgrade, so that I don't have to run the multi-step managed-layout flip on every node for every release.

Updating an off-cluster foreman-agent today is: download the release tarball, stage the binary into ~/Library/Application Support/llmkube/foreman-agent/versions/<ver>/, repoint the previous/current symlinks, and launchctl kickstart -k. It works (and is bug-#740-safe), but it is several manual steps per node per release. We just did it by hand on two nodes (M5 Max + Studio) for 0.8.16. This does not scale as the fleet grows.

Proposed Solution

Add brews: formulae for the edge agents, sourced from the existing release archives (LLMKube-foreman-agent_<ver>_darwin_<arch>.tar.gz, LLMKube-metal-agent_<ver>_darwin_<arch>.tar.gz), so brew install/upgrade llmkube-foreman-agent works.

The non-trivial part is service + per-node config, which the issue needs to resolve:

  • The foreman-agent runs as a launchd service with per-node flags (e.g. --max-context-tokens, --total-ram-gb, --tokens-per-second, --inference-base-url-host-override, --commit-author-name). A generic brew services plist would not carry these.
  • The current managed layout (versions/<ver> + current/previous symlinks) is essentially reimplementing what Homebrew's Cellar + relinking already does, so a brew-managed install could retire the custom layout for brew-managed nodes.
  • Options to preserve per-node config across brew upgrade:
    1. Agent reads config from an env file / config file (e.g. ~/.config/llmkube/foreman-agent.env or a TOML/YAML), so the launchd plist stays generic and survives upgrades. (Requires the agent to support file/env config in addition to flags.)
    2. A brew services-compatible plist that sources that env file.
  • Note the interaction with the in-cluster declarative self-update path (Approach A / AgentRelease): a brew-managed binary and a controller-driven symlink-flip self-update are two different update models and should not fight. Brew is the manual upgrade UX; the declarative rollout is separate. The issue should state which nodes use which (or how they coexist).

Alternatives Considered

Additional Context

  • This pairs with the existing "helm and brew for the edge" fleet-update direction.
  • Current tap config: .goreleaser.yaml brews: (CLI only); the agent build ids are llmkube-foreman-agent and llmkube-metal-agent.
  • Per-node flag preservation is the reason make install-foreman-agent is unsafe for in-place updates today (it rewrites the plist from the template and drops the extra flags); a brew + external-config design should fix that class of problem too.
  • Related issues: #

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions