A simple agent with LangChain and OpenAI
Write a small Python agent with LangChain
in workspace acme. It has two tools, one that reads the server’s clock
and one that counts words, and it answers a question you give it on the
command line.
The OpenAI key never goes in a command, a script or the chat with your
agent: devmachine secrets stores it on your computer and writes it into
the project’s .env file in the workspace.
You need: a Linux VPS (tested on Debian and Ubuntu), or a local VM (this guide needs no domain), and an OpenAI API key from platform.openai.com.
Before you start: machine, skills, workspace
curl -fsSL https://mydevmachine.sh/install.sh | sh
devmachine setup
devmachine skills add
devmachine workspaces new acme
devmachine sync
Already have a machine? Skip setup. Already have the workspace? Skip the
last two. See getting started for what each command
does.
By hand
1. Make the Python project
Inside the workspace (devmachine ssh acme):
mise use -g uv@latest
uv init agent && cd agent
uv add langchain langchain-openai python-dotenv
echo .env >> .gitignore
uv installs Python packages, and Python
itself if the machine lacks the right version. mise, from the mise
package every new workspace gets, installs it without root. uv init makes
a git repository, so the last line keeps the key file out of it.
2. Deliver the OpenAI key
On your computer:
devmachine secrets set OPENAI_API_KEY --workspace acme --env-file agent/.env --push
value for OPENAI_API_KEY:
stored acme/OPENAI_API_KEY
delivered acme/OPENAI_API_KEY -> agent/.env
Paste your key at the prompt. It does not echo, so it never reaches your
shell history. The value is kept in your OS keychain, and --push writes it
at once to /home/acme/agent/.env, a file only acme can read:
OPENAI_API_KEY='<your key>'
The path after --env-file is relative to the workspace’s home. Any other
lines in that file stay as they were. To change the key later, run the same
command again. See credentials: your app’s own
secrets.
3. Write the agent
Inside the workspace, in ~/agent:
cat > agent.py <<'EOF'
import sys
from datetime import datetime
from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain.tools import tool
load_dotenv()
@tool
def get_time() -> str:
"""Return the current date and time on this server."""
return datetime.now().isoformat(timespec="seconds")
@tool
def word_count(text: str) -> int:
"""Count the words in a piece of text."""
return len(text.split())
agent = create_agent(
model="openai:gpt-6-luna",
tools=[get_time, word_count],
system_prompt="You are a helpful assistant. Use your tools when they help.",
)
if __name__ == "__main__":
question = " ".join(sys.argv[1:]) or input("Question: ")
result = agent.invoke({"messages": [{"role": "user", "content": question}]})
print(result["messages"][-1].content)
EOF
load_dotenv() reads .env and sets OPENAI_API_KEY, which LangChain’s
OpenAI model reads by itself. The docstring of each tool is what the model
reads to decide when to call it. gpt-6-luna is OpenAI’s low-cost model;
any name from OpenAI’s model list
works after openai:.
4. Ask it something
Inside the workspace, in ~/agent:
uv run agent.py "What time is it on the server, and how many words are in 'hello big world'?"
The model calls both tools, then writes one answer with the server’s time
and the number 3. With no question after agent.py, it asks you for one.
With your agent
Open a session on your own computer (devmachine skills add taught it the
CLI) and say:
In my devmachine workspace acme, make a uv project ~/agent with langchain,
langchain-openai and python-dotenv, and write agent.py: a LangChain
create_agent agent on openai:gpt-6-luna with two tools, get_time and
word_count, that answers the question given on the command line. Read
OPENAI_API_KEY from agent/.env. Do not ask me for the key: tell me the
devmachine secrets command to run myself.
The agent installs uv, makes the project and writes agent.py over SSH.
The key is yours to give: run the devmachine secrets set ... --push
command from step 2 yourself, and paste the key at its prompt, never into
the chat. Then the agent can run uv run agent.py to test it.
Check it: inside the workspace, cd ~/agent && uv run agent.py "How many words are in 'hello big world'?" prints an answer that says 3.
Troubleshooting
OpenAIAuthenticationError: Error code: 401 ... 'code': 'invalid_api_key'
means the code works: the packages are installed, the tools load, the key
was read and the request reached OpenAI, which refused the key. The key is
wrong, not the code. The message shows only its first and last letters,
such as Incorrect API key provided: sk-test-**********-key. Copy a fresh
key from OpenAI and run step 2 again.
openai.OpenAIError: Missing credentials. Please pass an api_key ...
means no key was found. Check that ~/agent/.env exists and that you run
the agent from ~/agent. On your computer, devmachine secrets list --workspace acme shows where the key goes:
acme/OPENAI_API_KEY -> agent/.env
To test the tools without the model or a key, inside ~/agent:
uv run python -c 'from agent import get_time, word_count; print(get_time.invoke({})); print(word_count.invoke({"text": "hello big world"}))'
It prints the server’s time, then 3.
Next steps
- Put the agent behind a small web API and give it a domain:
FastAPI with TLS shows the app, then
devmachine expose addpublishes it. - Give it memory between questions: pass a
checkpointertocreate_agentand the samethread_idon each call — see LangChain’s short-term memory. - Add more tools: any Python function with type hints and a docstring,
marked
@tool.
Source: LangChain — Quickstart
Where to go next
- Security
Logins and secrets
See what a workspace is missing, then sign in and hand over tokens with credentials, login and secrets.
Beginner
- Agents
Agno AgentOS with a control plane
Serve Agno AgentOS and its control plane dashboard, each at its own subdomain with HTTPS.
Advanced
- Get started
Try it on your own computer first
Try devmachine on a virtual machine on your own computer before you pay for a server.
Beginner