Agent examples¶
Each example on this page is a complete custom agent you can copy: a chat page in your browser, a notebook server, and Claude Code working on tasks in the background. Your first agent shows the simplest one.
A chat app in the browser¶
These steps run a Streamlit chat page in the container, which you open in your Mac browser:
- Make a project and add the libraries:
- Write
app.pyin the project folder:
import os
import streamlit as st
from openai import OpenAI
client = OpenAI()
model = os.environ["GMLX_MODEL"]
st.title("Chat desk")
if "messages" not in st.session_state:
st.session_state.messages = []
for message in st.session_state.messages:
st.chat_message(message["role"]).write(message["content"])
if prompt := st.chat_input("Ask the local model"):
st.session_state.messages.append({"role": "user", "content": prompt})
st.chat_message("user").write(prompt)
stream = client.chat.completions.create(
model=model, messages=st.session_state.messages, stream=True)
reply = st.chat_message("assistant").write_stream(stream)
st.session_state.messages.append({"role": "assistant", "content": reply})
- Add the agent to your gmlx config file:
launch:
agents:
chat-desk:
runtime: python
command: [streamlit, run, app.py, --server.address, "127.0.0.1",
--server.port, "8501", --server.headless, "true"]
web_port: 8501
- Launch it from the project folder:
launch opens the page once Streamlit answers. End the session with
gmlx launch chat-desk --stop. --server.headless true stops Streamlit
from asking for an email address on its first start. Use an @instruct
model, because the page shows nothing while a thinking model thinks.
A notebook server¶
These steps run JupyterLab in the container, with notebooks that call the model:
- Make a project with JupyterLab and the OpenAI library:
- Make a token for the page with
openssl rand -hex 16, and add the agent to your gmlx config file with it:
launch:
agents:
lab:
runtime: python
command: [jupyter, lab, --ip, "127.0.0.1", --port, "8888",
--no-browser, --allow-root]
web_port: 8888
env: [JUPYTER_TOKEN=<your token>]
-
Launch it from the project folder with
gmlx launch lab --detach, open the address thatlaunchprints, and sign in with the token. -
In a notebook, call the model:
import os
from openai import OpenAI
reply = OpenAI().chat.completions.create(
model=os.environ["GMLX_MODEL"],
messages=[{"role": "user", "content": "Name three uses of a local model."}])
print(reply.choices[0].message.content)
- End the session with
gmlx launch lab --stopfrom the project folder.
Notebooks are saved in the project folder. Keep the token secret: any
program on the Mac can open the page, and a notebook runs any code in the
container. Jupyter needs --allow-root because the container runs as root.
Coding agents in the background¶
These steps give Claude Code one task at a time in the background, each in its own git worktree. You read and merge the branches it commits.
- Make the folder
~/containers/claude-bgwith a one-line Containerfile:
- Add the agent to your gmlx config file:
launch:
agents:
fixer:
build: ~/containers/claude-bg
api: anthropic
command: [claude, -p, --dangerously-skip-permissions]
env: [IS_SANDBOX=1, DISABLE_AUTOUPDATER=1]
- Make a worktree for the task, and start the agent in it with the task
after
--:
cd ~/src/app
git worktree add ../app-mul -b add-mul
cd ../app-mul
gmlx launch fixer --detach -- "Add a mul function to calc.py, then commit it."
-
Follow the sessions with
gmlx launch --list, which names each one's output file. -
When the session has ended, read the branch, merge it, and clean up:
cd ~/src/app
git diff main add-mul
git merge add-mul
(cd ../app-mul && gmlx launch fixer --remove-home)
git worktree remove ../app-mul
-p runs the task after --, and the session ends when Claude Code
finishes. launch sets IS_SANDBOX=1 and DISABLE_AUTOUPDATER=1 only for
the built-in claude-code client, so the agent sets both in env. Each
worktree is a separate project, so several tasks can run at once. The agent commits with your git name, because the session shares the
repository's git folder.
Run --remove-home before you remove the worktree, because launch finds
the private home by the folder. Read each branch before you merge it, since
it can change
files that the Mac runs.
For a repository you do not trust, follow
A session for code you do not trust.