After this lesson, you will be able to: Set up a Python environment, understand the ReAct loop, and implement a simple tool-calling agent from scratch using the Anthropic or OpenAI API.
Code-first means you write the agent in Python, no frameworks, just the SDK. This intro sets up the environment and builds the simplest possible agent: a ReAct loop with one tool. By the end you'll see clearly what frameworks like LangChain are abstracting.
This is a free introductory lesson. No purchase required.
1. Install Python 3.11+. Check: `python --version`.
2. Create a project folder + virtual env: `python -m venv venv && source venv/bin/activate` (Windows: `venv\Scripts\activate`).
3. Install the SDK: `pip install anthropic` (or `pip install openai`).
4. Get an API key, console.anthropic.com or platform.openai.com. Save it as env var: `export ANTHROPIC_API_KEY=sk-...`.
5. Test: `python -c "import anthropic; print(anthropic.Anthropic().messages.create(model='claude-3-5-haiku-latest', max_tokens=100, messages=[{'role':'user','content':'hi'}]).content[0].text)"`
One file. Plain Python. Anthropic SDK.
import anthropicclient = anthropic.Anthropic()messages = []while True:user_input = input('You: ')if user_input == 'quit':breakmessages.append({'role': 'user', 'content': user_input})response = client.messages.create(model='claude-sonnet-4-6',max_tokens=1024,messages=messages,)reply = response.content[0].textmessages.append({'role': 'assistant', 'content': reply})print(f'Claude: {reply}')
Now it's an agent. Tool definition + dispatch + loop.
import anthropicclient = anthropic.Anthropic()tools = [{'name': 'calculator','description': 'Evaluates a math expression. Input is a string like "2+2*3".','input_schema': {'type': 'object','properties': {'expression': {'type': 'string'}},'required': ['expression'],},}]def run_tool(name, args):if name == 'calculator':return str(eval(args['expression'])) # demo only, eval is unsafe in productionraise ValueError(f'Unknown tool: {name}')messages = [{'role': 'user', 'content': 'What is 17 * 234, plus 9001?'}]while True:response = client.messages.create(model='claude-sonnet-4-6', max_tokens=1024, tools=tools, messages=messages,)if response.stop_reason == 'end_turn':print(response.content[-1].text); breakmessages.append({'role': 'assistant', 'content': response.content})tool_uses = [b for b in response.content if b.type == 'tool_use']tool_results = [{'type': 'tool_result', 'tool_use_id': t.id, 'content': run_tool(t.name, t.input),} for t in tool_uses]messages.append({'role': 'user', 'content': tool_results})
A complete ReAct agent in 25 lines. The model decides when to use the calculator. You dispatch the tool, return the result, loop. Frameworks like LangChain wrap this exact pattern with more bells and whistles, but you now know what's underneath.