Skip to content

BotCity Python Pro skill

The botcity-python-pro skill turns Claude into a specialized programming partner for production-level BotCity automations. It applies modern Python 3.11+ patterns adapted to the reality of RPA: credential security, layered error handling, UI/logic separation, and respect for the BotCity Runner deploy format. Works in both Portuguese and English.


Prerequisites

  • Claude Code installed and configured
  • Python 3.11 or higher
  • Existing BotCity project or intention to create one from scratch
  • Access to BotCity Maestro (required for production deployment)
  • Runtime dependencies pinned in the project's requirements.txt:
pip install botcity-framework-web botcity-maestro-sdk pydantic python-dotenv

Install the skill

Copy the botcity-python-pro/skill.md file to Claude Code's skills folder:

cp botcity-python-pro/skill.md ~/.claude/skills/botcity-python-pro.md

Note

The skill is activated automatically when Claude detects BotCity context — code with DesktopBot, WebBot, botcity-maestro-sdk, references to DataPool or Runner. You don't need to invoke it manually.


Choose the operating mode

The skill operates in four modes. Explicitly declare which one you need at the start of the conversation:

Mode When to use What to expect
Scaffold Brand new project Complete src/ structure, pinned requirements.txt, test skeleton
Refactor Improve existing bot Structured diagnosis (Critical/Important/Nice-to-have) before changing code
Fix Specific bug Surgical fix without opportunistic refactoring
Review Structured feedback Categorized list of findings without applying changes

Tip

Be explicit: "new bot from scratch" and "just fix this timeout" generate very different responses.


Create a bot from scratch

Use a descriptive prompt with the bot's responsibilities:

Create a BotCity bot from scratch that:
- Consumes items from a DataPool called "invoices_to_process"
- Logs into a web portal using Maestro credentials
- Downloads the PDF for each invoice and uploads it as an artifact
- Handles invalid invoices by marking the item as error without aborting

The skill generates the following project structure:

my_bot/
├── bot.py
├── requirements.txt
├── pyproject.toml
├── README.md
├── .env.example
├── .gitignore
├── resources/
├── src/
│   ├── config.py
│   ├── pages/
│   ├── services/
│   ├── domain/
│   ├── utils/
│   └── exceptions.py
└── tests/
    ├── unit/
    └── fixtures/

Warning

The BotCity Runner reads requirements.txt, not pyproject.toml. If you use uv, run uv export --no-dev --no-hashes --format requirements-txt > requirements.txt before packaging the .zip for deployment.


Refactor an existing bot

Paste the code directly into the conversation and ask for a review:

Review this bot for me. It's a plain Selenium bot we migrated to BotCity
last month and it's having issues in production. [paste code]

The skill runs the diagnosis checklist and returns structured findings:

## Findings

### Critical (2)
1. Hardcoded API key in src/api_client.py:14 — move to Maestro Credentials
2. CPF logged without masking in src/services/customer.py:47 — apply mask_cpf()

### Important (3)
...

### Suggested order
1. Fix Criticals (security)
2. Importants 1-3 (reliability)
3. Niceties can wait

Which one would you like me to address first?

Configure credentials and DataPool

The skill generates the canonical bootstrap pattern with fallback for local development:

BotMaestroSDK.RAISE_NOT_CONNECTED = False
maestro = BotMaestroSDK.from_sys_args()

def get_secret(label: str, key: str) -> str:
    try:
        return maestro.get_credential(label=label, key=key)
    except Exception:
        load_dotenv()
        value = os.getenv(f"{label.upper()}_{key.upper()}")
        if not value:
            raise CredentialError(f"Missing credential: {label}/{key}")
        return value

For DataPool consumption with three-level error handling:

pool = maestro.get_datapool(label="invoices_to_process")

while pool.has_next():
    entry = pool.next(task_id=maestro.task_id)
    if entry is None:
        break
    try:
        item = InvoiceItem.model_validate(entry.values)
        service.process_invoice(item)
        entry.report_done()
    except BusinessError as e:
        entry.report_error(message=str(e))
    except FatalError:
        entry.unhold()
        raise

Warning

In case of FatalError, call entry.unhold() before re-raising the exception. Without this, the item stays held in the pool and is lost.


Expected result

When using the botcity-python-pro skill, your project will have:

  • requirements.txt with all runtime dependencies pinned with ==, without dev tools
  • Separation into three layers: pages/ (UI/selectors), services/ (business logic), domain/ (Pydantic models)
  • Custom exception hierarchy: RecoverableError, BusinessError, FatalError
  • Credentials consumed via Maestro SDK with .env fallback for local execution
  • Input data validated with Pydantic before any processing
  • PII (emails, tokens, sensitive data) masked in logs and artifacts
  • Type hints strictly applied in services/ and domain/, tolerant in pages/
  • Unit tests covering 60-70% of services/, domain/, and utils/