11 min read1 hour ago
–
When Clawdbot started gaining traction in mid December, I wanted it immediately.
An AI assistant that books flights, manages calendars, and fixes production bugs? All from a WhatsApp message? I was ready to install it that afternoon.
Press enter or click to view image in full size
Then I read the GitGuardian report. 181 leaked secrets. A healthcare company’s Notion credentials exposed. A fintech startup’s Kubernetes cluster wide open. Telegram bot tokens everywhere.
I closed the browser tab.
But I couldn’t stop thinking about it. The capabilities were real. The demand was real (Best Buy sold out of Mac Minis in San Francisco). The security was the problem.
So I built my own [enterprise-grade AI agent](https://medium.com/ai-native-enterprise/to…
11 min read1 hour ago
–
When Clawdbot started gaining traction in mid December, I wanted it immediately.
An AI assistant that books flights, manages calendars, and fixes production bugs? All from a WhatsApp message? I was ready to install it that afternoon.
Press enter or click to view image in full size
Then I read the GitGuardian report. 181 leaked secrets. A healthcare company’s Notion credentials exposed. A fintech startup’s Kubernetes cluster wide open. Telegram bot tokens everywhere.
I closed the browser tab.
But I couldn’t stop thinking about it. The capabilities were real. The demand was real (Best Buy sold out of Mac Minis in San Francisco). The security was the problem.
So I built my own enterprise-grade AI agent with the same capabilities as Clawdbot.
What made Clawdbot so compelling
Peter Steinberger’s project hit 9,000 GitHub stars in 24 hours. Within a week, it crossed 80,000 stars and attracted 2 million visitors. The name changed twice in three days (first to Moltbot after Anthropic’s trademark request, then to OpenClaw), but the signal was unmistakable.
Developers don’t want another chatbot. They want an AI that operates.
Clawdbot delivered: browser automation, calendar management, scheduled tasks, persistent memory across sessions. One user saved $4,200 negotiating a car price through it. Another cataloged their entire wine cellar.
I wanted that for my work. I run a B2B agency, and my days are split between client calls, competitive research, content workflows, and deliverable tracking. The idea of an AI assistant that could handle the tedious parts while I focused on strategy was too good to ignore.
But I also handle client credentials, access sensitive platforms, and can’t afford to be the next case study in a security blog.
Press enter or click to view image in full size
The problem with Clawdbot (and why I couldn’t use it)
Casey Newton of Platformer captured it perfectly after her own experiment: “the specific ways in which it broke persuaded me to uninstall Clawdbot from my computer.” The initial setup was “the high-water mark.”
Another reviewer found that calendar management produced chaos. Appointments consistently appeared one day off. The tool couldn’t create recurring events, resulting in dozens of incorrect individual entries that the bot kept trying to re-add.
But the real issue wasn’t the bugs. It was the architecture.
Clawdbot creates files, captures tool outputs, and logs session transcripts that may include credentials pasted by users or fetched from external sources. The documentation warns about this. The mitigation? A .gitignore rule.
That’s not enterprise security.
I needed the capabilities without the liability. So I broke down what Clawdbot actually does and rebuilt each piece properly.
What I actually built
Clawdbot’s 700+ plugins across 28 categories sound impressive, but the capabilities that matter cluster into four areas. These are the ones I use daily.
Press enter or click to view image in full size
- Messaging interface: I send commands from Slack and get results without context-switching.
- Browser automation: My agent scrapes competitor pricing, extracts content from web apps, and fills forms when APIs don’t exist.
- Scheduled tasks: Every morning at 7am, I get a briefing. Every Monday, I get a competitive landscape update. No manual triggering.
- Persistent memory: My agent remembers client contexts, project details, and my preferences across sessions.
Here’s how I built each one.
The foundation: Claude Agent SDK
Everything runs on the Claude Agent SDK. This isn’t a wrapper around Claude. It’s the same tools, agent loop, and context management that power Claude Code, now programmable in Python.
The core loop is simple: gather context → take action → verify work → repeat.
Press enter or click to view image in full size
The SDK provides built-in tools out of the box: Read, Write, Edit, Glob, and Grep for file operations; Bash for terminal commands and scripts; WebSearch and WebFetch for current information.
The key parameter is allowed_tools. Unlike Clawdbot, which requests excessive permissions by default, I specify exactly what each agent can do. My research agent gets ["Read", "Glob", "Grep", "WebSearch", "WebFetch"]. My file operations agent gets ["Read", "Edit", "Bash"]. Nothing more.
from claude_agent_sdk import query, ClaudeAgentOptionsasync for message in query( prompt="Find all client mentions in yesterday's Slack threads and summarize", options=ClaudeAgentOptions( allowed_tools=["Read", "Grep", "WebFetch"], mcp_servers={"slack": slack_config} )): if hasattr(message, "result"): print(message.result)
This is the foundation everything else builds on.
Layer 1: Slack as my interface
I chose Slack because my team already lives there. The official Slack MCP server handles OAuth authentication that respects existing permissions, and workspace admins can see exactly what the integration accesses.
Press enter or click to view image in full size
My setup connects Slack to the Agent SDK through the MCP server. When I message my agent channel, it processes the request, runs the appropriate tools, and responds in the thread.
from claude_agent_sdk import query, ClaudeAgentOptionsslack_config = { "command": "npx", "args": ["@anthropic-ai/slack-mcp-server"]}async def handle_slack_message(message_text: str, channel: str): async for message in query( prompt=message_text, options=ClaudeAgentOptions( mcp_servers={"slack": slack_config}, allowed_tools=["mcp__slack__*", "Read", "WebSearch"] ) ): if hasattr(message, "result"): await post_to_slack(channel, message.result)
The key difference from Clawdbot: every action is logged, permissioned, and auditable. My IT setup can see exactly what the agent accessed. When a client asks “what data does your AI touch?”, I have answers.
Layer 2: Browser automation that actually works
This is where Clawdbot earned its reputation. Booking flights. Filling forms. Scraping competitor data.
I use Microsoft’s Playwright MCP server, and the difference in approach matters.
Clawdbot uses screenshots. The model looks at pixels and decides where to click. This is slow, expensive (vision models), and ambiguous.
Playwright MCP uses the accessibility tree. Instead of pixels, the agent sees structured data about every element on the page. No vision models needed. Deterministic actions. Fast.
Press enter or click to view image in full size
Here’s what my competitor research workflow looks like:
playwright_config = { "command": "npx", "args": ["@playwright/mcp@latest"]}async def research_competitor(competitor_url: str): async for message in query( prompt=f"Go to {competitor_url}/pricing and extract their plan tiers, " f"features, and prices. Format as markdown.", options=ClaudeAgentOptions( mcp_servers={"playwright": playwright_config} ) ): if hasattr(message, "result"): return message.result
One insight from months of use: browser automation works best for async, research-style tasks. Scraping pricing pages. Gathering reviews from Reddit. Extracting data from web apps without APIs.
It struggles with tight feedback loops. I tried using it for real-time coding assistance and the latency killed the experience. Design your workflows accordingly.
Layer 3: Scheduled tasks (the killer feature)
This is what I use most. Clawdbot can send daily briefings and run recurring jobs, but with zero audit trail and full machine access.
I use APScheduler for simple recurring tasks and have Temporal ready for complex multi-step workflows.
Press enter or click to view image in full size
My morning briefing runs at 7am every weekday:
from apscheduler.schedulers.asyncio import AsyncIOSchedulerfrom apscheduler.triggers.cron import CronTriggerfrom claude_agent_sdk import query, ClaudeAgentOptionsasync def morning_briefing(): async for message in query( prompt="""Generate my morning briefing: 1. Check calendar for today's meetings and prep needed 2. Summarize any urgent Slack threads from #clients and #team 3. Flag any platform alerts or monitoring notifications 4. List any deliverables due this week Format as a concise bullet list I can scan in 2 minutes.""", options=ClaudeAgentOptions( mcp_servers={ "slack": slack_config, "google-calendar": calendar_config, "memory": memory_config } ) ): if hasattr(message, "result"): await post_to_slack("#gavriel-briefing", message.result)scheduler = AsyncIOScheduler()scheduler.add_job( morning_briefing, CronTrigger(hour=7, minute=0, day_of_week="mon-fri"))scheduler.start()
I also run a Monday morning competitive landscape check:
async def weekly_competitor_scan(): competitors = ["competitor1.com", "competitor2.com", "competitor3.com"] async for message in query( prompt=f"""Research these competitors for any changes this week: {', '.join(competitors)} Check for: - Pricing changes - New feature announcements - Blog posts or content - Social media activity Compare to what you remember from last week.""", options=ClaudeAgentOptions( mcp_servers={ "playwright": playwright_config, "memory": memory_config } ) ): if hasattr(message, "result"): await post_to_slack("#competitive-intel", message.result)scheduler.add_job( weekly_competitor_scan, CronTrigger(hour=8, minute=0, day_of_week="mon"))
The memory integration is key here. The agent remembers last week’s findings and can flag what actually changed.
Layer 4: Persistent memory
Standard AI starts every conversation from zero. Clawdbot maintains context across sessions using local files. I use the MCP Memory Server, which stores knowledge as a graph of entities, observations, and relations.
Press enter or click to view image in full size
memory_config = { "command": "npx", "args": ["@modelcontextprotocol/server-memory"], "env": {"MEMORY_FILE_PATH": "./memory-work.jsonl"}}# Agent automatically stores and retrieves contextasync for message in query( prompt="Remember that the Acme Corp deadline moved to March 15 " "and they prefer weekly updates on Fridays", options=ClaudeAgentOptions( mcp_servers={"memory": memory_config} )): pass # Memory stored# Later, in a different session...async for message in query( prompt="What's the status on the Acme Corp project?", options=ClaudeAgentOptions( mcp_servers={"memory": memory_config} )): # Agent knows about the March 15 deadline and Friday updates print(message.result)
A feature Clawdbot lacks: context isolation. I run separate memory files for work and personal contexts (memory-work.jsonl, memory-personal.jsonl). An agent running in my work context can’t accidentally access personal memory.
For client work, each client gets their own memory namespace. When I’m working on Acme Corp, the agent has full context on that engagement without bleeding into other clients.
Where it runs: xpander.ai
One thing Clawdbot users quickly discover: scheduled tasks don’t work when your laptop sleeps. You need infrastructure that stays on.
I deploy everything on xpander.ai. They have native Claude Code integration, so my Agent SDK code runs in their cloud with Slack integration, persistent state, and proper infrastructure out of the box.
The setup was straightforward. xpander has a Coding Agent template that uses their Claude Code connector. I started with that, customized the logic, and deployed. Now my agents run 24/7 without me managing servers.
What I get from xpander:
- Cloud infrastructure that doesn’t sleep when I do
- Slack-native deployment (my agents live in channels, not a separate app)
- Persistent state across sessions (handled automatically)
- Centralized logs and observability
- Team access without sharing credentials
The alternative was spinning up a VPS, managing uptime, handling Slack OAuth myself, and building state management from scratch. xpander handles all of that so I can focus on the agent logic.
The security layer (what makes this enterprise-grade)
This is what separates my setup from a Clawdbot installation. And it’s why 181 secrets leaked from Clawdbot users.
Press enter or click to view image in full size
I don’t store API keys in environment variables or config files. Akeyless provides dynamic secrets: credentials generated on-demand, automatically rotated, and revoked when no longer needed.
What drew me to Akeyless over self-hosted alternatives: they have an AI Agent Identity Provider specifically designed for this use case. My agents get verifiable, federated identities with short-lived credentials. When my agent needs database access, Akeyless issues a time-limited token with read-only permissions. When the task completes, the token expires. Nothing persists.
import akeylessfrom claude_agent_sdk import query, ClaudeAgentOptions# Configure Akeyless clientconfiguration = akeyless.Configuration(host="https://api.akeyless.io")with akeyless.ApiClient(configuration) as api_client: api = akeyless.V2Api(api_client) # Get dynamic secret (credentials auto-expire after TTL) body = akeyless.GetDynamicSecretValue( name='/agents/readonly-db-access', token=access_token ) creds = api.get_dynamic_secret_value(body) # Use the short-lived credentials async for message in query( prompt="Analyze client engagement trends for Q4", options=ClaudeAgentOptions( mcp_servers={ "postgres": { "command": "npx", "args": ["postgres-mcp-server"], "env": { "POSTGRES_USER": creds['username'], "POSTGRES_PASSWORD": creds['password'] } } } ) ): pass
The SaaS model means I’m not managing vault infrastructure on top of everything else. One less thing to maintain.
Permission Scoping
Every agent runs with minimum necessary permissions. My research agent can read and search. My file operations agent can edit. Neither can do what the other does.
This is the opposite of Clawdbot’s approach, which requests excessive OAuth scopes by default. Users had to push back just to get read-only calendar access.
Audit Trail
Every action is logged. When I ask “what did the AI access yesterday?”, I can answer precisely. For client work, this isn’t optional. It’s required.
What I actually use it for
After a few weeks of iteration, these are my core workflows:
My morning briefing runs at 7am weekdays. It combines calendar, Slack, platform alerts, and deliverables into something I can scan in 2 minutes. Saves 20 minutes of context-switching.
Competitive research runs Monday mornings. Browser automation scrapes competitor sites, memory recalls last week’s state, and the agent flags what changed. Used to take half a day manually.
Before client kickoff calls, the agent pulls all context from the client files, generates a briefing doc, and identifies gaps I need to fill. Consistent prep without the manual assembly.
For content research, I send prompts like “Find discussions about [topic] on Reddit, HackerNews, and industry forums. Summarize the main pain points and what solutions people are using.” Returns a structured report I can work from.
Weekly client updates are the simplest. The agent drafts status updates based on deliverables completed, pulling from memory and Slack activity. I edit and send. Cuts the writing time by 70%.
What you gain
Press enter or click to view image in full size
Building this took more work than running npx clawdhub@latest install. But I gained:
- Audit trails. Every action logged, traceable, compliant. When clients ask what data the AI touches, I have answers.
- Access controls. Each agent has exactly the permissions it needs. A bug in my research agent can’t compromise my production systems.
- Credential management. Dynamic secrets, automatic rotation, instant revocation. No tokens in
.envfiles. Nothing to leak. - Reliability. Scheduled tasks run on Temporal with automatic retries and state persistence. If something fails at 3am, it recovers gracefully.
- Context isolation. Client A’s data never bleeds into Client B’s workflows. Work and personal stay separate.
The Clawdbot explosion showed us what developers want: AI that operates, not just opines. The 181 leaked secrets showed us what happens when you build it without security.
I wanted both: the capabilities and the safety. Now I have it.
The stack
Press enter or click to view image in full size
What’s next
I’m still iterating. Current experiments:
- Multi-agent workflows using xpander’s Agent Graph System, where specialized agents hand off to each other (research → analysis → draft)
- Voice interface via the Gemini Live API for hands-free briefings during my commute
- Client-facing automation where the agent handles routine client requests directly in Slack
The foundation is solid. Now I’m expanding what it can do.
If you’re building something similar, I’d love to hear about it. The tooling has finally caught up to the vision. The question is what we build with it.