When Your AI Agent Has the Keys to Everything

A real e-commerce incident where an AI agent with unrestricted API access broke everything. What went wrong, and how to set up automations that can't.

March 10, 2026
7 min read
Tags
aiautomationsecuritywoocommerceklaviyoopenclawpython

The message came in at an odd hour. The client's e-commerce was broken in multiple places at once: orders erroring out, email lists deleted in Klaviyo, product data changed without explanation, pages returning 500s. My first instinct was a breach. Someone got into the server, or a plugin update went sideways.

It wasn't a breach.

It was an AI agent running with full API access to everything, executing tasks it had been told to do, doing them exactly as instructed. The instructions were wrong. The agent didn't know that. It didn't have a way to know.

This is the part of the AI automation hype cycle that doesn't show up in the LinkedIn posts about replacing entire departments with a single prompt.

What actually happened

The client had decided to use AI agents to automate parts of the operation that I had been handling manually as part of my consulting scope. Reasonable decision. The execution was where it fell apart.

They used OpenClaw, set it up with API keys for GA4, Klaviyo, Metorik, and WooCommerce, and wrote prompts with another AI tool to define what the agents should do. That's it.

No validation. No staging environment. No human review step.

The API keys were generated with full permissions because that is what the AI prompt told him to do.

The agent wasn't malfunctioning. That's the part that matters. It was following instructions that were underspecified, and it had enough access to make those instructions catastrophic. Garbage in, garbage out, except the garbage had admin credentials.

Three things that would have stopped this

Minimum permissions, before anything else. This is not a nice-to-have. It's the first thing you set up, before you write a single prompt or run a single test. Every API integration should start with the question: what is the least access this agent needs to do its job?

For WooCommerce, that means creating a consumer key scoped to read-only. In the WooCommerce admin under Users > Your Profile, or via the REST API, you can generate keys with explicit read, write, or read/write permissions. If the agent is reporting on orders, it needs read. It does not need write. Full stop.

import os
from woocommerce import API

wcapi = API(
    url=os.getenv("WC_STORE_URL"),
    consumer_key=os.getenv("WC_READ_CONSUMER_KEY"),      # read-only key
    consumer_secret=os.getenv("WC_READ_CONSUMER_SECRET"),
    version="wc/v3",
    timeout=10
)

# Enforce the constraint at the code level too.
# If the key doesn't prevent it, the wrapper should.
class ReadOnlyClient:
    def __init__(self, api):
        self._api = api

    def get(self, endpoint, **kwargs):
        return self._api.get(endpoint, **kwargs)

    def post(self, *args, **kwargs):
        raise PermissionError("Write operations are not permitted in this context.")

    def put(self, *args, **kwargs):
        raise PermissionError("Write operations are not permitted in this context.")

    def delete(self, *args, **kwargs):
        raise PermissionError("Write operations are not permitted in this context.")

Two layers of protection: the API key itself is read-only, and the client wrapper raises an error if anything tries to write anyway. If you ever accidentally use the wrong key, the second layer catches it.

For Klaviyo, the private API key can be scoped by resource and permission level in the account settings under API Keys. Create a separate key for each integration. One key for the agent that reads list metrics. A different key, with write access, locked in a separate vault, for the humans who manage the lists.

import os
import requests

def get_klaviyo_lists():
    # This key has lists:read scope only.
    # It cannot create, update, or delete lists.
    headers = {
        "Authorization": f"Klaviyo-API-Key {os.getenv('KLAVIYO_LISTS_READ_KEY')}",
        "revision": "2024-10-15",
        "accept": "application/json",
    }
    response = requests.get(
        "https://a.klaviyo.com/api/lists/",
        headers=headers,
        timeout=10
    )
    response.raise_for_status()
    return response.json()

For WordPress and its plugins, the REST API supports application passwords (Settings > Users > Application Passwords) that can be used in place of your main account credentials. They don't inherit admin privileges automatically, and you can revoke them individually without changing your main password. For WooCommerce specifically, use the built-in API key system rather than application passwords — it gives you finer control over what each key can do.

Nothing goes directly to production. This should be obvious, but not everyone remembers that.

Every automation, before it runs in production, must run in a staging environment with a copy of real data. Staging WooCommerce, staging Klaviyo (use a test account or sandbox mode), staging everything. If it doesn't exist, create it. Yes, you might have a cost by maintaining a staging and/or development environment, but it's considerably less than recovering from an agent that deleted six months of your data.

For OpenClaw specifically, you can configure environment profiles in your .env file. Keep them strictly separate:

# .env.staging
WC_STORE_URL=https://staging.yourstore.com
WC_READ_CONSUMER_KEY=ck_staging_readonly_...
KLAVIYO_LISTS_READ_KEY=pk_staging_...

# .env.production
WC_STORE_URL=https://yourstore.com
WC_READ_CONSUMER_KEY=ck_prod_readonly_...
KLAVIYO_LISTS_READ_KEY=pk_prod_...

The agent should never have access to production credentials until it has been validated in staging. Not "mostly validated." Validated. Keep it running for a week. See if the results are correct. Check if some action was executed out of the limitations you defined. Then send to production.

A human sees it before it ships. Every automated workflow I build has at least one point where a human reviews the output before it becomes permanent. A generated product description goes into a review queue, not directly into WooCommerce. A Klaviyo segment update gets a confirmation step. A GA4 annotation gets drafted, not published.

This isn't because AI can't act autonomously. It's because when it acts incorrectly, someone needs to have seen it first. The accountability has to land somewhere. If nobody reviewed it, nobody can explain what happened or prevent it from happening again.

A simple approval pattern in Python looks like this:

def request_approval(action_description: str, payload: dict) -> bool:
    print(f"\nPending action: {action_description}")
    print(f"Payload: {payload}")
    response = input("Approve? (yes/no): ").strip().lower()
    return response == "yes"

def update_product_description(product_id: int, new_description: str):
    approved = request_approval(
        f"Update description for product {product_id}",
        {"description": new_description[:100] + "..."}
    )
    if not approved:
        print("Action cancelled.")
        return
    # Only reaches here with explicit approval
    wcapi.put(f"products/{product_id}", {"description": new_description})

In a real workflow this would be a Slack message with approve/reject buttons, or a simple web interface, not a CLI prompt. The pattern is the same either way. Set your automation to say "I'm going to do X, this imply that Y will change, proceed?" and then wait for your input.

Setting up OpenClaw with minimal access

When you configure OpenClaw, the tools you expose to the agent define what it can do. Don't expose tools you don't need. If the agent's job is reporting, it gets read tools. If it's sending emails, it gets one specific email tool with a constrained scope. The principle is the same as API permissions: the narrowest possible access that still lets the job get done.

Store credentials in environment variables, never in the prompt or the agent configuration file directly. Use a secrets manager if you're running this in production infrastructure. Rotate keys regularly, and log every API call the agent makes. If something goes wrong, you want a full record of what the agent did and when.

The question worth sitting with: for every AI automation currently running in your stack, do you know exactly what it's allowed to do? And do you have a record of what it actually did, and whos responsible in case of failure?


I work with teams to build AI-powered workflows that don't require a post mortem. If you're implementing automation in a production environment and want a second opinion before you connect the first API key, that's something I can help with.

Read More Posts

Explore other articles and insights

Back to Blog

© 2026 Paulo H. Alkmin. All rights reserved.