mirror of
https://github.com/gravitational/teleport.git
synced 2026-10-12 02:15:01 +00:00
[v18] Add a how-to guide for beamctl/beam-init (#660)
Export-Source-Commit: aa7cf706ba26683063fea50ac16139ab879ab3bb
This commit is contained in:
committed by
Gus Rivera
parent
e4f6f38866
commit
5ecff0f5e9
@@ -0,0 +1,320 @@
|
||||
---
|
||||
title: Manage Long-Running Agents on Teleport Beams
|
||||
description: Provides instructions on getting up and running with beamctl, a tool for managing services on Teleport Beams.
|
||||
sidebar_label: Long-Running Agents
|
||||
tags:
|
||||
- how-to
|
||||
- ai
|
||||
page_type: "how-to"
|
||||
---
|
||||
|
||||
{/* cSpell:ignore beamctl, morsecode */}
|
||||
|
||||
You can use Teleport Beams to securely manage long-running agentic workloads,
|
||||
such as complex coding projects. Each beam deploys with a tool, `beamctl`, that
|
||||
allows you to manage services that continue running after you exit your SSH
|
||||
session.
|
||||
|
||||
In this guide, you will learn how to manage long-running agentic workloads on a
|
||||
Teleport beam by walking through a small demo project.
|
||||
|
||||
## How it works
|
||||
|
||||
Teleport Beams are micro VM sandboxes for running agentic workloads, hosted on
|
||||
the Teleport Cloud infrastructure. `beam-init` is the init system for a Teleport
|
||||
beam, similar to `systemd` in that it runs as PID 1 and spawns other processes
|
||||
that run on the host. `beamctl` is a CLI for managing processes spawned by
|
||||
`beam-init`, which it communicates with over a local Unix socket.
|
||||
|
||||
These processes are called **services**. Unlike `systemd`, which loads service
|
||||
definition files from disk, `beam-init` requires the user to declare new
|
||||
services while executing them over the command line. This is consistent with the
|
||||
ephemeral nature of a Teleport beam, which expires after 24 hours.
|
||||
|
||||
This guide illustrates the following `beamctl` commands in action:
|
||||
|
||||
|Command|Description|
|
||||
|---|---|
|
||||
|`beamctl start <command>`|Create a service. Assigns a random service name (e.g., `2341e33f4f3c550f`) unless you provide a name with the `--name` flag.|
|
||||
|`beamctl stop <service name>`|Terminate a service process.|
|
||||
|`beamctl restart <service name>`|Terminate a service process and start it again using its original command.|
|
||||
|`beamctl list`|List all services and their statuses.|
|
||||
|`beamctl logs <service name>`|Show the output of a service.|
|
||||
|
||||
<details>
|
||||
<summary>Deleting a service</summary>
|
||||
|
||||
If you terminate a `beam-init` service with `beamctl stop`, the default behavior
|
||||
is for `beam-init` to retain the service in its list of managed services. To
|
||||
remove a service from the list of services `beam-init` tracks, run the following
|
||||
command:
|
||||
|
||||
```code
|
||||
$ beamctl stop --prune <service name>
|
||||
```
|
||||
|
||||
Otherwise, `beam-init` does not allow you to start a service with the same name
|
||||
as an existing one, even if that service is stopped.
|
||||
|
||||
</details>
|
||||
|
||||
For a full list of commands, run the following on your beam:
|
||||
|
||||
```code
|
||||
$ beamctl help
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This guide requires a Teleport Beams account. [Start your free
|
||||
trial](https://www.beams.run/).
|
||||
|
||||
In the demo project we'll use for this guide, you will run two continuous agent
|
||||
workloads to build a simple web application:
|
||||
|
||||
- **Agent 1:** Runs tests and gets them to pass by writing and optimizing code.
|
||||
- **Agent 2:** Writes tests and designs testable function signatures, but leaves
|
||||
implementations up to Agent 1.
|
||||
|
||||
Agent 2 writes tests that handle edge cases Agent 1 hasn't addressed yet. This
|
||||
forces the agents to adopt a test-driven development (TDD) workflow and prevents
|
||||
the agent writing the application code from adding trivial tests.
|
||||
|
||||
<Admonition type="warning">
|
||||
|
||||
The demo we run in this guide skips permissions in agent prompts. Since an agent
|
||||
on a Teleport beam inherits the permissions of the user who started the beam, we
|
||||
recommend that you authenticate to Teleport as a user with no access to
|
||||
Teleport-protected resources before starting this guide.
|
||||
|
||||
</Admonition>
|
||||
|
||||
## Step 1/2. Set up the demo project
|
||||
|
||||
The demo project we'll create in this guide lets users enter Morse code using a
|
||||
browser button and converts it to text.
|
||||
|
||||
<Admonition type="tip">
|
||||
|
||||
Feel free to use another project idea. If you do, read through the rest of the
|
||||
guide first to understand the relevant workflows.
|
||||
|
||||
</Admonition>
|
||||
|
||||
Create a Teleport beam and set up a project so that your agents have a place to
|
||||
carry out their work:
|
||||
|
||||
1. Create a beam and begin an SSH session with it:
|
||||
|
||||
```code
|
||||
$ tsh beams add
|
||||
```
|
||||
|
||||
1. On the beam, set up a project directory:
|
||||
|
||||
```code
|
||||
$ mkdir morsecode
|
||||
$ cd morsecode
|
||||
```
|
||||
|
||||
1. Set up your project:
|
||||
|
||||
```code
|
||||
$ npm init
|
||||
```
|
||||
|
||||
1. Name the package `morsecode` and accept all the `npm` defaults.
|
||||
|
||||
1. Install Vite, which we'll use to set up the NodeJS project, and `vitest` for
|
||||
testing:
|
||||
|
||||
```code
|
||||
$ npm install -D vitest vite@~8.2.0
|
||||
```
|
||||
|
||||
1. Add empty directories:
|
||||
|
||||
```code
|
||||
$ mkdir tests src
|
||||
```
|
||||
|
||||
1. Start a dev server, which reloads automatically when source files change:
|
||||
|
||||
```code
|
||||
$ beamctl start --name=server -- \
|
||||
bash -c 'export HOME=/home/beams; \
|
||||
cd /home/beams/morsecode; \
|
||||
npx vite --host --port=8080;'
|
||||
Started service server
|
||||
```
|
||||
|
||||
`beamctl start` starts a service managed by the `beam-init` init system,
|
||||
which manages all processes that run on a Teleport beam. Here we set the home
|
||||
directory as the one in which we created our Vite project to ensure `npm` can
|
||||
work as expected.
|
||||
|
||||
The server must run on port `8080` so you can visit it via Teleport later in
|
||||
the guide.
|
||||
|
||||
1. Copy the following text to a file called SPEC.md on the beam:
|
||||
|
||||
```markdown
|
||||
# Morse code in your browser
|
||||
|
||||
When the user taps a button, the app reads it as Morse code and converts text
|
||||
to a readout below the button. There is a collapsable Morse code key as a
|
||||
reference for the user.
|
||||
```
|
||||
|
||||
1. Start the testing agent with `claude`, which comes preinstalled on the beam
|
||||
(as does `codex`). Every 10 seconds, the testing agent adds new tests to
|
||||
implement the application and address potential edge cases. Like the coding
|
||||
agent we'll start next, the testing agent has a limit of 30 executions,
|
||||
amounting to around five minutes of work:
|
||||
|
||||
```code
|
||||
$ beamctl start --name=tester -- bash -c ' \
|
||||
export HOME=/home/beams; \
|
||||
export count=0; \
|
||||
cd /home/beams/morsecode; \
|
||||
while [ $count -lt 30 ]; do \
|
||||
claude -p --dangerously-skip-permissions < /dev/null "\
|
||||
Read SPEC.md and the existing test files under tests. Identify one \
|
||||
behavior from the spec that is not covered by an existing test yet, \
|
||||
e.g., a new function, or an additional edge case for a function \
|
||||
you have already tested. If a test calls a function that does not exist \
|
||||
yet, import it in the new test and assume it has a testable function \
|
||||
signature, but do not create or modify anything in src. Another agent \
|
||||
will define functions and get tests to pass. Do not modify or remove \
|
||||
existing tests."; \
|
||||
sleep 10; \
|
||||
count=$((count+1)); \
|
||||
done;'
|
||||
Started service tester
|
||||
```
|
||||
|
||||
1. Start the coding agent:
|
||||
|
||||
```code
|
||||
$ beamctl start --name=coder -- bash -c ' \
|
||||
export HOME=/home/beams; \
|
||||
export count=0; \
|
||||
cd /home/beams/morsecode; \
|
||||
while [ $count -lt 30 ]; do \
|
||||
if ! npx vitest run --silent; then \
|
||||
claude -p --dangerously-skip-permissions < /dev/null "\
|
||||
Read SPEC.md and existing test files under tests. Get the tests to \
|
||||
pass by editing files in src. Maintain a minimal Vite entrypoint at \
|
||||
index.html to wire everything up."; \
|
||||
fi; \
|
||||
sleep 10; \
|
||||
count=$((count+1)); \
|
||||
done;'
|
||||
Started service coder
|
||||
```
|
||||
|
||||
1. Make sure all services are running as expected. All should report `running`:
|
||||
|
||||
```code
|
||||
$ beamctl list
|
||||
bootstrap (running PID=2)
|
||||
coder (running PID=168)
|
||||
server (running PID=5817)
|
||||
tester (running PID=136)
|
||||
```
|
||||
|
||||
<details>
|
||||
<summary>Problem starting a service?</summary>
|
||||
|
||||
If a service has not started correctly, check its logs:
|
||||
|
||||
```code
|
||||
$ beamctl logs tester
|
||||
$ beamctl logs coder
|
||||
$ beamctl logs server
|
||||
```
|
||||
|
||||
If the problem has to do with the command you ran to start a service (e.g., a
|
||||
typo), prune the service and start it again with the correct command:
|
||||
|
||||
```code
|
||||
$ beamctl stop --prune <service>
|
||||
$ beamctl start <correct command>
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
1. Exit your session.
|
||||
|
||||
```code
|
||||
$ exit
|
||||
logout
|
||||
the connection was closed on the remote side at <timestamp>
|
||||
```
|
||||
|
||||
Once you exit the session, the agents you spawned with `beamctl` will continue
|
||||
their work.
|
||||
|
||||
## Step 2/2. Check your app
|
||||
|
||||
After a few minutes, your agents should have made substantial progress on your
|
||||
demo project.
|
||||
|
||||
1. Find the beam you created so you can access it:
|
||||
|
||||
```code
|
||||
$ tsh beams ls
|
||||
```
|
||||
|
||||
1. Publish the application. The command below enrolls your demo project as a
|
||||
Teleport-protected web app. Assign <Var name="beam-name" /> to the name of
|
||||
your beam:
|
||||
|
||||
```code
|
||||
$ tsh beams publish <Var name="beam-name" />
|
||||
```
|
||||
|
||||
1. Follow the prompts to authenticate to Teleport and visit your app.
|
||||
|
||||
1. In your terminal, SSH into your beam:
|
||||
|
||||
```code
|
||||
$ tsh beams ssh <Var name="beam-name" />
|
||||
```
|
||||
|
||||
1. Show the status of all the `beamctl` services you started:
|
||||
|
||||
```code
|
||||
$ beamctl list
|
||||
bootstrap (running PID=2)
|
||||
coder (running PID=168)
|
||||
server (running PID=5817)
|
||||
tester (running PID=136)
|
||||
```
|
||||
|
||||
1. Check the logs of your `beamctl` services. For example, you can see the
|
||||
tester discussing the tests it has added:
|
||||
|
||||
```code
|
||||
$ beamctl logs tester
|
||||
```
|
||||
|
||||
You can add the `--follow` flag to stream the service's logs to your
|
||||
terminal.
|
||||
|
||||
1. If the services are still running, you can terminate their processes with the
|
||||
following command:
|
||||
|
||||
```code
|
||||
$ beamctl stop tester
|
||||
$ beamctl stop coder
|
||||
```
|
||||
|
||||
1. If any services have stopped, and you would like them to resume their work,
|
||||
you can run the following command to restart them. For example:
|
||||
|
||||
```code
|
||||
$ beamctl restart coder
|
||||
$ beamctl restart tester
|
||||
$ beamctl restart server
|
||||
```
|
||||
Reference in New Issue
Block a user