Skip to content
imarch.dev
Back to blog
· 3 min read

The Bot Learned to Do Things

ai fastapi claude code продукт

The bot had been answering questions on the site for two weeks. Answering well - in three languages, with context, with caching. But it was a monologue going both ways. Ask, answer. Ask again, answer again. When a visitor wanted to get in touch, the bot would list contact details and step aside.

Today I tried teaching it to actually do things.

AI chatbot learns to take action

The problem

Someone in the chat says “I’d like to discuss a project.” The bot replies: “Here’s the email, here’s Telegram, here’s the phone number.” The person nods. Copies the address. Switches to their email client. Composes a message from scratch. Or doesn’t - closes the tab and forgets.

Between “I want to get in touch” and “I actually wrote the email,” more people drop off than you’d think.

Tool use

Anthropic’s API has a mechanism called tool use - you can give the model functions, and it decides when to call them. Not based on keywords, not with regex. The model reads the conversation and understands intent.

I gave the bot two tools.

The first one captures leads. The bot asks short questions, one at a time:

  • Can I reach Ilyas?
  • What’s your name?
  • Marat
  • How should we reach you - email, phone, Telegram?
  • @marat_dev
  • What would you like to discuss?
  • Architecture audit
  • Passed it to Ilyas, he’ll get back to you.

The message with all the details is already in my inbox. No forms involved.

The second one sends CVs. A visitor asks for a resume, the bot collects their email and sends a message with a link to the CV page. They can view it online and download the PDF. The data is always current - the CV on the site gets updated, and the bot automatically links to the latest version.

  • Can I get Ilyas’s CV?
  • What email should I send it to?
  • hr@company.kz
  • Sent.

Under the hood

Two tool definitions with simple schemas. Haiku 3 handles it well - doesn’t mix up the tools, doesn’t fire them when it shouldn’t. The descriptions are written as directives: “only call when all fields are collected, otherwise ask.”

Emails go out via Resend, STARTTLS on port 587. During deployment I discovered the host blocks port 465 - Claude Code found the issue on its own and switched ports. Emails are localized in three languages.

Rate limit is shared across both tools - three emails per IP per day. Format validation, injection filtering. Responses that involve tool calls skip the cache - every request is unique.

Why this matters

The bot stopped being a FAQ machine. It now has two actions beyond “answer a question.” Architecturally, adding a third is a twenty-minute job: a tool definition, a handler, one line in the prompt.

What’s interesting isn’t that the bot can send an email. It’s that it steers the conversation toward that outcome, asks the right questions, and picks the right moment. No scripts, no decision trees. Just a model reading context.

200 lines of new code. An hour and a half of work. One of those evenings where the result is wildly disproportionate to the effort.


Give it a try - the chat button is in the bottom-right corner. Say you’d like to get in touch, or ask for a CV. Or reach out directly if the bot hasn’t learned what you need yet.

Share:

Related posts