This repository provides a ready-to-use browser development environment for the workshop.
You do not need to install Python, Docker, VS Code, or the OpenAI SDK locally.
- Sign in to GitHub.
- Open this repository.
- Click Use this template → Open in a codespace.
- Wait until VS Code opens in your browser.
Python and the required packages are installed automatically. The workshop also creates a local .env file and opens .env plus hello_llm.py for you.
Open the .env tab. The CTFd URL and workshop category are already configured.
Replace these two placeholders with the credentials you received for the workshop:
OPENROUTER_API_KEY— your workshop LLM API keyCTFD_TOKEN— your CTFd access token (in CTFd: Settings → Access Tokens → Generate)
Do not share these credentials. The .env file is ignored by Git, and a pre-commit hook blocks accidental commits of OpenRouter keys, CTFd tokens, and dotenv files.
Run this in the VS Code terminal:
python hello_llm.pyYou should get a short response from the workshop model.
The starter uses:
qwen/qwen3.8-flash
through OpenRouter's OpenAI-compatible API. We have only enabled this model for the workshop key. If you supply your own OpenRouter API key, you can use any model available to your account.
hello_llm.py exposes three local tools to the model:
get_challenge_description— load the visible description and metadata for a challengespawn_challenge— start or reuse your per-user challenge instancesubmit_flag— submit a candidate flag to CTFd
The CTFd token stays local in .env; ctf.py uses it to authenticate to the CTFd API and it is not sent to the LLM.
A challenge can be selected by workshop number, by a case-insensitive name substring, or by a raw CTFd challenge id.
For example, change the user message in hello_llm.py to something like:
Get the description for challenge 3 and start my instance.
Then run:
python hello_llm.pyThe model can call the CTFd tools automatically when needed.
hello_llm.py sends a single message — it never actually runs the tools.
harness.py is the missing loop: it spawns a challenge instance and lets the
model drive the CTFd tools until the flag is accepted or its step budget runs
out.
python harness.py 3 # by workshop number
python harness.py haystack # by name
python harness.py -7619548 # by raw CTFd idWhen it spawns an instance it hands the model the connection info CTFd returns, so the agent has a live target to work against. Offline challenges (1, 2) have no instance; the model is told the files are the challenge.
The harness wires the three CTFd tools for you. Reaching into the target — an
http_request tool, a run_shell tool — is the workshop exercise: add them to
ctf.TOOLS and ctf.TOOL_FUNCTIONS and they appear in the harness
automatically. challenges in the lab repo lists what each challenge forces you
to build.
Edit the user message in hello_llm.py, or add your own tools and re-run
harness.py:
python hello_llm.py
python harness.py 3When you are done with one part of the exercise, you can continue working in the same file or copy it to a new one.
A codespace created from the template is initially just your cloud workspace. If you want to keep your work permanently, use Publish to GitHub from the Source Control view in VS Code. GitHub will create a repository in your account containing your work.
You can also download individual files if you prefer.