← Plugin catalog
Developer Tools

CrowdStrike AgentWorks

CrowdStrike v1.0.1

Build and manage AI agents

Create a free account to save this plugin.

Competitor profile

Developer declarations; not independently tested. Listing last checked Nov 4, 2026. Package observed Nov 3, 2026.

Declared capabilities

  • Interactive
  • Write

Not specified in the available declarations: limitations, pricing & account requirements.

Onboarding example

Create a CrowdStrike Charlotte AI AgentWorks agent

View package source →

Description

From the marketplace listing

Interact with Charlotte AI AgentWorks to create, configure, invoke, and monitor AI agents. Manage knowledge bases, discover available models and tools, and orchestrate agent workflows.

Language: English · Automatically detected from descriptions.

What changed

Keywords

Files & skills

File archives

Plugin package63 files · 117 KBBrowse files →
Skill instructions
agents22.7 KB

View saved version →

---
name: agents
description: >
  Manage Charlotte AI AgentWorks agent lifecycle.
  Create/update agents, query by filter, get agent details, publish agents, and ANALYZE execution patterns.
  **Analysis provides actionable prompt improvements based on actual execution traces, not just statistics.**
  Uses the native FalconPy `Agents` and `AgentVersions` classes.
  TRIGGER when user asks to create/update/query/publish/analyze/improve an agent.
  DO NOT TRIGGER for agent invocation (use invocation skill), knowledge bases (use knowledge-bases skill),
  or discovery (use discovery skill).
  DO NOT TRIGGER for enable/disable agent (publish-only per v1 scope) or delete operations.
  DO NOT TRIGGER for agents defined in a Falcon Foundry app (manifest.yml `ai.agents`, `foundry agents create`);
  foundry-redirect handles those.
version: 1.0.1
updated: 2026-10-21
tags: [agentworks, charlotte, agents, lifecycle, falcon, analysis, optimization]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
allowed-tools: Bash(cd *), Bash(../../scripts/python.sh:*)
metadata:
  category: agent-management
---

# Agents Lifecycle & Analysis

> **Read this first.**
>
> You are an AI assistant with expertise in Charlotte AI AgentWorks agent lifecycle management
> and **execution trace analysis for prompt optimization**.
> Your role is to help users create, update, query, get, publish, and **ANALYZE** agents
> using the native FalconPy `Agents` and `AgentVersions` service classes.
>
> **IMMEDIATE ACTIONS REQUIRED:**
> 1. Read this entire skill file before taking any action
> 2. Verify credentials are configured (TOML profile or env vars)
> 3. Only use the scripts documented below — never guess agent IDs or parameters
> 4. Run scripts via `cd ${CLAUDE_PLUGIN_ROOT}/skills/agents && ../../scripts/python.sh scripts/<script>.py`
> 5. Parse script output and present results clearly to the user
> 6. **When user asks to improve/optimize an agent, ALWAYS run analyze_agent.py first**
>
> **MUST NOT:**
> - Enable or disable agents (publish-only per v1 scope)
> - Delete agents (delete operations excluded)
> - Guess agent IDs — always query first
> - Give generic advice — always analyze actual execution traces first

## Running the scripts

All scripts must be invoked through the managed venv wrapper:

```bash
cd ${CLAUDE_PLUGIN_ROOT}/skills/agents
../../scripts/python.sh scripts/<script_name>.py [args]
```

- **Claude Code**: `${CLAUDE_PLUGIN_ROOT}` is substituted with the plugin's install path before this text reaches the model. Use the braced form; a bare `$CLAUDE_PLUGIN_ROOT` is never exported into the Bash tool's shell.
- **Other hosts (Codex, Copilot CLI, Cursor, Antigravity)**: these don't set `CLAUDE_PLUGIN_ROOT`. `cd` to the folder you loaded this SKILL.md from (e.g. `~/.agents/skills/agents`) and run `../../scripts/python.sh scripts/<script_name>.py [args]` from there.

Uses the native FalconPy `Agents` and `AgentVersions` service classes.

## Prerequisites

- **Credentials**: Same as knowledge-bases skill (TOML profile or env vars)
- **API scopes**: `csrn:charlotte-ai:agent:definition` (read + write)
- **Python 3.14+**: Auto-managed
- **FalconPy 1.6.6+**: Provides the `Agents` service class (shared version floor enforced by `common/scripts/auth.py` across all skills, not just this one)

## Core Workflows

### 📋 Inspecting Agent Definitions Before Recommending

**CRITICAL:** When evaluating agents from Claude Code's available agent types list (visible in system reminders) or from tool metadata, you MUST inspect the full agent definition before recommending or using it.

#### ID Disambiguation - CRITICAL

**Use `version_group_id`, NOT `agent_id` (or just `id`):**

- **`version_group_id`** → The stable identifier across all versions of an agent → **USE THIS**
- **`agent_id` or `id`** → A specific version instance → Using this will fail with "failed to retrieve agent"

**Where to find `version_group_id`:**
- In agent types list metadata: Look for `version_group_id` field
- In tool discovery output: Listed as "Version group:" or `version_group_id`
- In agent metadata: Extract from `version_group` or `version_group_id` field

#### What Version You'll See - CRITICAL

When you inspect an agent using `version_group_id`, `agent_get.py` returns:

1. **Latest PUBLISHED version** (if one exists) ← Most common case
2. **Latest version** (if no published version exists) ← Draft only

**Important implications:**

- **Modifying a published agent creates a DRAFT version** → The draft is NOT returned by `agent_get.py`
- **Inspection shows production behavior** → You see what's actually running, not work-in-progress
- **Draft changes are invisible until published** → If an agent was recently modified but not published, you won't see those changes

**Example:**
```
Published agent: v1 (system prompt: "You are a security analyst...")
↓ User modifies agent
Draft version: v2 (system prompt: "You are an expert security analyst...")
↓ Inspect with agent_get.py
Result: Shows v1 (published), NOT v2 (draft)
↓ Publish v2
↓ Inspect with agent_get.py
Result: Shows v2 (now published)
```

**Example from tool discovery:**
```
• Vulnerability Response Agent
  - ID: agents/0ad0ec8a-c49a-4784-9541-8c931aa0a365/...  ← DON'T USE THIS
  - Version group: 4ff1fc7a-2181-405d-a6d7-95b549eb7a10    ← USE THIS
```

#### Workflow for Agent Inspection:

1. **Extract `version_group_id`** (NOT `agent_id` or `id`) from the metadata
2. **Get the complete definition**:
   ```bash
   cd ${CLAUDE_PLUGIN_ROOT}/skills/agents
   ../../scripts/python.sh scripts/agent_get.py --ids <version_group_id>
   ```
3. **Inspect the full definition**:
   - System prompt - does it match the task's needs?
   - Tools - does it have the right capabilities?
   - Model - is it appropriate for the complexity?
   - Knowledge base IDs - does it have relevant context?
4. **Only recommend/use** if the actual definition is a strong fit for the task

**Why:** Agent names and brief descriptions can be misleading. A "security-agent" might be configured for compliance checks, not threat hunting. The system prompt and tool configuration reveal the true capabilities.

**Example - Correct ID Usage:**
```bash
# Tool metadata shows:
#   ID: agents/0ad0ec8a-c49a-4784-9541-8c931aa0a365/vulnerability_response_agent
#   Version group: 4ff1fc7a-2181-405d-a6d7-95b549eb7a10

# ❌ WRONG - Using agent_id:
../../scripts/python.sh scripts/agent_get.py --ids 0ad0ec8a-c49a-4784-9541-8c931aa0a365
# Result: "failed to retrieve agent"

# ✅ CORRECT - Using version_group_id:
cd ${CLAUDE_PLUGIN_ROOT}/skills/agents
../../scripts/python.sh scripts/agent_get.py --ids 4ff1fc7a-2181-405d-a6d7-95b549eb7a10
# Result: Full agent definition with system prompt, tools, model

# Review output to confirm it has:
# - System prompt mentioning the specific security domain (e.g., "vulnerability triage")
# - Relevant tools (e.g., falcon_platform:get_vulnerabilities, not just generic tools)
# - Appropriate model for the task complexity
```

### 🔍 Analyze Agent Execution (START HERE for optimization)

**When to use:** User asks to "improve", "optimize", "debug", or "analyze" an agent.

1. **Analyze execution patterns** → `analyze_agent.py --agent-id <uuid> --days 7 --verbose`
   - Examines actual execution traces (not just statistics)
   - Identifies tool usage patterns, error contexts, version changes
   - Provides **actionable prompt improvements** with specific guidance
   - Shows performance anomalies and root causes

2. **Review recommendations** → Parse output for:
   - 🔧 **Unused tools** → Remove or add usage guidance to prompt
   - ⚠️ **Error-prone tools** → Add validation/error handling guidance
   - ⏱️ **Slow tools** → Add timeout warnings or optimization hints
   - 📊 **Common tool sequences** → Optimize prompt to guide workflows
   - 💭 **Excessive LLM calls** → Make prompt more decisive
   - 🔄 **Version changes** → Compare definitions to understand performance shifts

3. **Deep-dive specific traces** → Use invocation IDs from analysis with `inspect_invocation.py` (invocation skill)

4. **Apply improvements** → Update agent with `agent_upsert.py` using recommended prompt changes

**Example output:**
```
💡 Recommendations
1. 🔧 Unused tools: falcon_platform:get_host_details
   Either remove OR add: 'When user asks about host details, use falcon_platform:get_host_details to...'

2. ⚠️ Tool 'falcon_platform:search_hosts' has high error rate: 45%
   Add validation: 'Before calling search_hosts, verify filter syntax...'

3. 📊 Common tool patterns:
    - search_hosts → get_host_details → format_response (12x)
   Consider optimizing prompt to guide this workflow explicitly.
```

### Create/Update Agent

**CRITICAL FOR UPDATES:** When updating an existing agent, preserve existing configuration unless explicitly instructed otherwise:
1. **Get current agent details** → `agent_get.py --ids <agent-id>` → read current model, tools, model_config
2. **Only modify what's requested** → Keep existing model, tools, model_config unless user specifically asks to change them or you have strong reasoning
3. **Pass all fields to upsert** → Even unchanged fields must be included in the upsert call

**Workflow:**

1. **For updates: Read existing agent first** → `agent_get.py --ids <id>` → capture current config
2. **Discover prerequisites only if changing tools/model**:
   - `models_search.py --limit 50` (discovery skill) → capture a model ID if changing model
   - `tools_get.py --search "specific capability"` (discovery skill) → capture tool IDs if changing tools
   - If the tool family is known, filter it first with
     `tools_get.py --category <category> --search "specific capability"`; see the discovery
     skill's category guide. This avoids similarly named tools from unrelated providers.
     - ⚠️ **Use specific search terms**: "host search", "detection query", "vulnerability scan", "logscale"
     - ❌ **Avoid generic terms**: "falcon", "crowdstrike" (matches everything in Falcon platform, useless results)
3. **Query agents by filter** (if you don't have agent ID) → `agent_search.py --filter "active_version.name:~'topic'"` (substring, case-insensitive) → returns agent IDs
4. **Create or update agent** → `agent_upsert.py`:
   - Create: omit `--id`, specify all required fields (returns agent ID + version ID)
   - Update: include `--id <uuid>`, pass existing values for unchanged fields (creates new version, returns version ID)
5. **PROPOSE test invocation before publishing** → Offer to test the new version:
   - Use invocation skill: `invoke_version.py --agent-id <agent-id> --version-id <version-id> --message "Test prompt"`
   - Note: Draft versions CAN be invoked via `invoke_version.py` (no publish required for testing)
   - Poll for completion: `get_messages.py --id <invocation-id>`
   - If issues found, return to step 4 to adjust
6. **Publish agent** → `agent_publish.py --id <agent-uuid> --version-id <version-uuid>` → makes version the published default

Stop after each script; confirm with user before proceeding.

## Script Reference

| Script | Purpose | Key Flags |
|--------|---------|-----------|
| `agent_search.py` | Query agent IDs by FQL filter | `--filter "active_version.name:~'term'"` (substring), `--limit 100` |
| `agent_get.py` | Get agent entities by IDs | `--ids <id> [id...]` |
| `agent_list.py` | List agents as a table (Name/Description/Last modified/Last modified by/Created by/Status) | `--name-contains`, `--created-by`, `--modified-since`, `--modified-before`, `--status {published,unpublished}`, `--sort {name,updated_at}` (default `updated_at`), `--order {asc,desc}` (default `desc`), `--limit` |
| `agent_upsert.py` | Create or update an agent | `--name`, `--model`, `--system-prompt`, `--tools`, `--knowledge-base-ids`, optional `--id` |
| `agent_publish.py` | Publish agent (make invocable) | `--id <uuid>`, `--version-id <uuid>` |
| `analyze_agent.py` | Analyze execution patterns & suggest improvements | `--agent-id <uuid>`, `--days 7`, `--verbose` |

All scripts support `--help` and `--json`.

### Finding/listing agents by topic, name, date, or status

**For a plain topic/name substring search**, use `agent_search.py` with the `:~` fuzzy operator —
one API call, works at any tenant size:

```bash
../../scripts/python.sh scripts/agent_search.py --filter "active_version.name:~'root access'"
../../scripts/python.sh scripts/agent_search.py --filter "active_version.description:~'privilege escalation'"
```

**For combined criteria** (name substring + date range + publish status all at once), sorted
table output, or pagination — use `agent_list.py` instead, which pages through all agents and
filters/sorts client-side (slower on large tenants, but supports multiple simultaneous filters
that `agent_search.py`'s single `--filter` string doesn't conveniently combine):

```bash
../../scripts/python.sh scripts/agent_list.py --name-contains "root access"
../../scripts/python.sh scripts/agent_list.py --modified-since 2026-09-01 --status published
../../scripts/python.sh scripts/agent_list.py --limit 5  # most recently modified first (default sort)
```

See `references/fql-filters.md` for the full confirmed filter/operator behavior — it has a
"History" section on how the wrong conclusion got written into this doc twice before the `:~`
operator was found; read it before trusting a new negative finding of your own.

`--sort` only accepts `name` or `updated_at` — there is no `modified` value, even though the
flag is about modification date; the sortable field is named `updated_at`. Since `updated_at desc`
is already the default, "most recent N agents" needs only `--limit N`, no `--sort`/`--order`.

**Always paste the resulting table directly into your chat response — do not just point at the
tool output.** Script stdout is plain text to the harness; it is not markdown-rendered. Only text
you write directly in your own reply renders as an actual table for the user.

**Pagination:** `agent_list.py` defaults to `--limit 20` and prints a trailer line after the table:
`Showing 1-20 of 47 matching agent(s).` and, if more remain, `MORE_RESULTS_AVAILABLE
next_offset=20 remaining=27`. When you see that trailer, do NOT silently fetch/dump everything or
silently truncate — tell the user how many more there are and ask if they want the next page (e.g.
via AskUserQuestion or a plain question). If they say yes, re-run with `--offset <next_offset>`
(same filters/sort) to get the next page.

**Always paste the resulting table directly into your chat response — do not just point at the
tool output.** Script stdout is plain text to the harness; it is not markdown-rendered. Only text
you write directly in your own reply renders as an actual table for the user.

## Input/Output Format Types

Agents support structured input validation and output formatting:

### Input Formats
- **`unstructured`** (default): Free-form text or JSON input, no schema validation
- **`json_with_schema`**: JSON input validated against a JSON Schema

### Output Formats
- **`unstructured`** (default): Free-form text response
- **`html`**: HTML-formatted response
- **`markdown`**: Markdown-formatted response
- **`json`**: JSON-formatted response (no schema enforcement)
- **`json_with_schema`**: JSON response validated against a JSON Schema

### Usage Examples

**Add input validation:**
```bash
../../scripts/python.sh scripts/agent_upsert.py \
  --id <agent-id> \
  --input-format json_with_schema \
  --input-schema '{
    "type": "object",
    "properties": {
      "prompt": {"type": "string", "description": "User question"},
      "severity": {"type": "string", "enum": ["low", "medium", "high"]}
    },
    "required": ["prompt"]
  }'
```

**Request structured JSON output:**
```bash
../../scripts/python.sh scripts/agent_upsert.py \
  --id <agent-id> \
  --output-format json_with_schema \
  --output-schema '{
    "type": "object",
    "properties": {
      "risk_score": {"type": "number"},
      "recommendations": {"type": "array", "items": {"type": "string"}}
    },
    "required": ["risk_score"]
  }'
```

## Usage Examples

### Query agents by name
```bash
../../scripts/python.sh scripts/agent_search.py --filter "active_version.name:~'Security'" --limit 10
```

### Get agent details
```bash
../../scripts/python.sh scripts/agent_get.py --ids <agent-id>
```

### Create a new agent
```bash
../../scripts/python.sh scripts/agent_upsert.py \
  --name "Root Access Hunter" \
  --description "Detects unauthorized root access" \
  --model bedrock.claude-4-6-sonnet \
  --system-prompt "You are a security agent that analyzes root access patterns..." \
  --tools <tool-id-1> <tool-id-2> \
  --knowledge-base-ids <kb-id>
```

### Update existing agent (creates new version)
```bash
# CRITICAL: Read current agent first to preserve existing config
../../scripts/python.sh scripts/agent_get.py --ids <agent-id>
# Note current: model, tools, model_config, knowledge_base_ids

# Update ONLY the system prompt, keep everything else the same
../../scripts/python.sh scripts/agent_upsert.py \
  --id <agent-id> \
  --system-prompt "Updated prompt with better instructions..." \
  --model <same-model-from-get> \
  --tools <same-tools-from-get> \
  --knowledge-base-ids <same-kbs-from-get>
# Pass ALL fields even if unchanged - API requires complete definition
```

### Publish agent
```bash
../../scripts/python.sh scripts/agent_publish.py \
  --id <agent-id> \
  --version-id <version-id>
```

### Analyze agent performance (last 7 days)
```bash
../../scripts/python.sh scripts/analyze_agent.py \
  --agent-id <agent-id> \
  --days 7 \
  --verbose
```

**What the analysis provides:**

1. **Version Detection** - Shows if agent definition changed
2. **Tool Usage Patterns** - Actual execution sequences (e.g., "search → get → format (12x)")
3. **Actionable Prompt Improvements** - Specific guidance with examples
4. **Error Context** - Which tools fail and why
5. **Performance Anomalies** - Version comparison with root cause
6. **Missing Capabilities** - Suggests additional tools based on patterns

See "Core Workflows → Analyze Agent Execution" above for detailed examples.

## Common Pitfalls / Counter-Rationalizations

| Thought | Reality |
|---------|---------|
| "The agent name tells me what it does" | **Inspect first.** Names can be misleading. Get the full definition with `agent_get.py --ids <version_group_id>` to see the actual system prompt, tools, and capabilities before recommending. |
| "I'll use the agent ID from the tool metadata" | **Use version_group_id instead.** The `agent_id` or `id` field refers to a specific version instance. Use `version_group_id` to retrieve the current definition. Using `agent_id` returns "failed to retrieve agent". |
| "I just modified the agent, so inspection will show my changes" | **Modifications create drafts.** `agent_get.py` returns the latest **published** version, not draft versions. Your changes are invisible until you publish them with `agent_publish.py`. |
| "I'll guess the agent ID" | **Query first.** Agent IDs are UUIDs; guessing fails. Use `agent_search.py`. |
| "I can update just the prompt" | **Read agent first, pass all fields.** When updating, get current config with `agent_get.py`, then pass ALL fields (model, tools, model_config, etc) even if unchanged. Omitted fields may be lost. |
| "I'll give generic optimization advice" | **Analyze first.** Run `analyze_agent.py` to get actionable insights from actual traces. Generic advice doesn't account for version changes, tool patterns, or error contexts. |
| "The agent is slow because of the model" | **Check execution patterns.** Could be tool sequences, excessive LLM calls, or unused/misconfigured tools. Analysis shows root cause. |
| "I'll enable the agent after publishing" | **Publish-only scope.** No enable/disable in v1. Publish = make invocable. |
| "I can delete an agent" | **Delete excluded.** No DELETE operations per v1 design. Agents persist. |
| "Model ID is just the model name" | **Model ID is a UUID.** Query models first with discovery skill, or user provides the UUID. |
| "agent_upsert returns only the agent ID" | **It also returns the version ID.** The version ID is required for `agent_publish.py --version-id`. |
| "Publish just needs the agent ID" | **Publish needs BOTH agent ID and version ID.** Use `PATCH` with `params={id}` and `body={version_id, is_published:true}`. |
| "I need to list invocations to analyze an agent" | **Use spans APIs instead.** Query spans by `agent_id`, hydrate them, extract `invocation_id` from attributes. Use `analyze_agent.py`. |
| "I'll filter agent_search by name" | **Top-level `name` doesn't work; `active_version.name:~'term'` does — use that.** `name:'...'` on `queries/agents/v2` silently matches nothing regardless of quoting/wildcard. The correct nested field is `active_version.name`, and the correct substring operator is `:~` (fuzzy, case-insensitive, matches anywhere) — NOT wildcard `*'...'` syntax, which also silently returns zero on this endpoint. `active_version.description:~'term'` works too. See `references/fql-filters.md` (which itself was wrong twice before this was nailed down — read the "History" section there before trusting a new negative finding). |
| "I'll pass multiple ids to agent_get as a comma-joined string" | **Must be a real list param.** `params={"ids": ",".join(ids)}` gets treated as one literal id and fails with "failed to retrieve agent". Use `params={"ids": ids}` (a list). See `references/api-reference.md`. |
| "I'll show the user a table by printing it from the script" | **Tool stdout isn't markdown-rendered.** Paste the table into your own chat response text, or the user just sees raw pipe-delimited text. |
| "I'll pass `--sort modified` since the flag is about modification date" | **`--sort` only accepts `name` or `updated_at`.** The sortable field is named `updated_at`, not `modified`, even though `--modified-since`/`--modified-before` exist as separate filter flags. Run `agent_list.py --help` if unsure, don't infer flag values from naming patterns. |
| "I'll write a severity/status/category enum from what sounds right" | **Query the tenant's actual values first.** A rewritten system prompt or `--input-schema`/`--output-schema` that hardcodes an assumed enum (e.g. `"enum": ["low", "medium", "high"]`) can silently mismatch the tenant's real configured values, breaking the workflow it was meant to automate. Check real invocation inputs/outputs (e.g. via `analyze_agent.py`, or `inspect_invocation.py` on a known trace) or whatever source of truth the workflow already uses before encoding an enum. |

## Reading Guide

| Task | Reference Doc |
|------|---------------|
| API endpoints and parameters | `references/api-reference.md` |
| FQL filter syntax | `references/fql-filters.md` |
| OAuth 2.0 + scopes | `../setup/SKILL.md` |

## FalconPy classes

This skill uses the native typed `Agents` class (`query_studio_agents`, `get_studio_agents`,
`create_or_update_agent`, `update_agent`) and `AgentVersions`, via `auth.get_agents_client()` and
`auth.call_native()`.

Referenced files: 9 — file references are metadata, not package contents.

agentworks5.02 KB

View saved version →

---
name: agentworks
description: >
  Orchestrator skill for Charlotte AI AgentWorks. Routes user intent to specialized sub-skills
  (agents, invocation, knowledge-bases, discovery, setup). Use this skill for high-level
  Charlotte AI AgentWorks requests or when unsure which sub-skill applies.
  TRIGGER when user mentions "Charlotte AI AgentWorks", "AgentWorks", "Agent Works", "Charlotte", "agentic studio", or any agent/KB operation.
  DO NOT TRIGGER for other CrowdStrike products (Fusion, Foundry, etc.). Agents or knowledge bases defined in a
  Falcon Foundry app (manifest.yml `ai.agents` / `ai.knowledge_bases`, `foundry agents create`) belong to
  foundry-skills; the foundry-redirect skill handles those.
version: 1.0.1
updated: 2026-10-21
tags: [agentworks, charlotte, orchestrator, routing]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
metadata:
  category: orchestration
---

# Charlotte AI AgentWorks Orchestrator

> **Read this first.**
>
> You are the Charlotte AI AgentWorks orchestrator. Your role is to **parse user intent** and delegate to
> the correct specialized sub-skill. You do NOT call APIs yourself — you route to skills that do.
>
> **IMMEDIATE ACTIONS:**
> 1. Read user intent carefully
> 2. Match intent to decision tree below
> 3. Delegate to the appropriate sub-skill
> 4. Only orchestrate multi-skill workflows if user requests it

## Decision Tree

```
User Intent
    │
    ├─ "create/update/query/publish agent"
    │   → /crowdstrike-charlotte-ai-agentworks:agents
    │
    ├─ "invoke agent" / "run agent" / "get agent results"
    │   → /crowdstrike-charlotte-ai-agentworks:invocation
    │
    ├─ "create/query KB" / "upload file to KB" / "KB audit"
    │   → /crowdstrike-charlotte-ai-agentworks:knowledge-bases
    │
    ├─ "list models/tools" / "discover templates" / "query versions"
    │   → /crowdstrike-charlotte-ai-agentworks:discovery
    │
    ├─ agent/KB inside a Foundry app ("manifest.yml", "ai.agents", "foundry agents create")
    │   → /crowdstrike-charlotte-ai-agentworks:foundry-redirect (points to crowdstrike-falcon-foundry)
    │
    ├─ "setup credentials" / "configure auth"
    │   → /crowdstrike-charlotte-ai-agentworks:setup
    │
    └─ Unclear / multi-step workflow
        → Ask clarifying questions, then route
```

## Intent → Sub-Skill Routing

| User Says... | Route To | Why |
|--------------|----------|-----|
| "Create an agent called X" | `agents` | Agent lifecycle |
| "Invoke agent Y with message Z" | `invocation` | Agent execution |
| "Upload file to KB" | `knowledge-bases` | KB file operations |
| "What models are available?" | `discovery` | Resource discovery |
| "Set up Charlotte AI AgentWorks" | `setup` | Credential configuration |
| "Add an agent to my Foundry app", `manifest.yml`, `ai.agents`, `foundry agents create` | `foundry-redirect` | Foundry owns agents defined in an app; this plugin manages API-created agents only |
| "Create agent, then invoke it" | **Multi-step** | Agents → publish → invocation |

## Full Lifecycle Coordination

For multi-step workflows (e.g., "create and invoke an agent"):

1. **agents**: Create agent → get ID
2. **agents**: Publish agent → confirm published
3. **invocation**: Invoke agent → get invocation_id
4. **invocation**: Get messages → return results

**Stop conditions:**
- After each step, confirm with user before proceeding
- If any step fails, stop and report error
- Never skip publish step (unpublished agents can't be invoked)

## Sub-Skill Summary

| Skill | Purpose | FalconPy Support |
|-------|---------|------------------|
| `agents` | Agent CRUD + publish | ✅ Native typed classes (`Agents`, `AgentVersions`) |
| `invocation` | Invoke + stream + messages | ✅ Native typed classes (`AgentInvocation`, `Stream`) |
| `knowledge-bases` | KB CRUD + files + audit | ✅ Native typed classes |
| `discovery` | Models/tools/templates/versions | ✅ Native typed classes (`Models`, `Tools`, `AgentTemplates`, `AgentVersions`, `Spans`) |
| `setup` | Credential config | Informational only |
| `foundry-redirect` | Declines Foundry-app agent requests and points to `crowdstrike-falcon-foundry` | Informational only |

## Common Pitfalls

| Thought | Reality |
|---------|---------|
| "I'll do everything in one skill" | **Delegate.** Each sub-skill is specialized; don't try to replicate their logic. |
| "User said 'agent' so use agents skill" | **Clarify first.** "Invoke agent" → invocation, "create agent" → agents. But also distinguish: Charlotte AI AgentWorks agents (this plugin) vs. your AI assistant's native agent/subagent system. Ask if ambiguous. |
| "I'll skip the orchestrator and call agents directly" | **Orchestrator adds value.** It enforces lifecycle order. |

## Credential Configuration

Credentials are configured via `/crowdstrike-charlotte-ai-agentworks:setup` or environment variables.

Only route to `setup` skill if user explicitly needs credential help.

## Reading Guide

For orchestration patterns and lifecycle workflows, see the skill-specific SKILL.md files.
discovery13 KB

View saved version →

---
name: discovery
description: >
  Discover available models, tools, templates, agent versions, and trace spans in Charlotte AI AgentWorks.
  Read-only queries using native FalconPy classes (`Models`, `Tools`, `AgentTemplates`, `AgentVersions`, `Spans`).
  TRIGGER when user asks to list/query/discover models, tools, templates, versions, or spans.
  DO NOT TRIGGER for agent creation/invocation (use agents/invocation skills) or knowledge bases.
version: 1.0.1
updated: 2026-10-21
tags: [agentworks, charlotte, discovery, models, tools, templates, falcon]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
allowed-tools: Bash(cd *), Bash(../../scripts/python.sh:*)
metadata:
  category: discovery
---

# Discovery

> **Read this first.**
>
> You are an AI assistant helping users discover Charlotte AI AgentWorks resources (models, tools, templates,
> versions, spans). All operations are **read-only queries** using native FalconPy classes (`Models`, `Tools`, `AgentTemplates`, `AgentVersions`, `Spans`).
>
> **IMMEDIATE ACTIONS REQUIRED:**
> 1. Read this entire skill file
> 2. Verify credentials configured
> 3. Run scripts via `cd ${CLAUDE_PLUGIN_ROOT}/skills/discovery && ../../scripts/python.sh scripts/<script>.py`
>
> **MUST NOT:**
> - 
> - Modify discovered resources (read-only skill)

## Running the scripts

```bash
cd ${CLAUDE_PLUGIN_ROOT}/skills/discovery
../../scripts/python.sh scripts/<script_name>.py [args]
```

- **Claude Code**: `${CLAUDE_PLUGIN_ROOT}` is substituted with the plugin's install path before this text reaches the model. Use the braced form; a bare `$CLAUDE_PLUGIN_ROOT` is never exported into the Bash tool's shell.
- **Other hosts (Codex, Copilot CLI, Cursor, Antigravity)**: these don't set `CLAUDE_PLUGIN_ROOT`. `cd` to the folder you loaded this SKILL.md from (e.g. `~/.agents/skills/discovery`) and run `../../scripts/python.sh scripts/<script_name>.py [args]` from there.

## Prerequisites

- **Credentials**: Same as other skills
- **API scopes**: `csrn:charlotte-ai:agent:definition` (read), `:template`, `:metrics`
- **FQL Knowledge**: Span queries use Falcon Query Language (FQL) syntax - see `docs/FQL_SYNTAX_REFERENCE.md`

## Core Workflow

All discovery scripts follow a two-step pattern:

### Step 1: Query for IDs
- **Query models** → `models_search.py --limit 50` → returns model IDs (filter by ID only, not name)
- **Query tools** → `tools_search.py --filter 'name:"..."'` → returns tool IDs
- **Query templates** → `templates_search.py --filter 'category:"..."'` → returns template IDs
- **Query versions** → `versions_search.py --filter 'agent_id:"..."'` → returns version IDs
- **Query spans** → `spans_search.py --filter 'trace_id:"..."'` → returns span IDs

### Step 2: Hydrate entities (for full details)
- **Get agent entities** → `agent_get.py --ids <id1> <id2>` (agents skill)
- **Get span entities** → `spans_get.py --ids <id1> <id2>` (discovery skill)

Query endpoints return opaque IDs; entity endpoints return full details.

## Inspecting Agent Definitions Before Recommending

**CRITICAL:** When evaluating agents from Claude Code's available agent types list (visible in system reminders) or from tool discovery output, you MUST inspect the full agent definition before recommending or using it.

### ID Disambiguation - CRITICAL

**Use `version_group_id`, NOT `agent_id` (or just `id`):**

- **`version_group_id`** → The stable identifier across all versions of an agent → **USE THIS**
- **`agent_id` or `id`** → A specific version instance → Using this will fail with "failed to retrieve agent"

**Where to find `version_group_id`:**
- In agent types list metadata: Look for `version_group_id` field
- In tool discovery output: Listed as "Version group:" or `version_group_id`
- In agent metadata: Extract from `version_group` or `version_group_id` field

### What Version You'll See - CRITICAL

When you inspect an agent using `version_group_id`, the agents skill's `agent_get.py` returns:

1. **Latest PUBLISHED version** (if one exists) ← Most common case
2. **Latest version** (if no published version exists) ← Draft only

**Important implications:**

- **Modifying a published agent creates a DRAFT version** → The draft is NOT returned
- **Inspection shows production behavior** → You see what's actually running, not work-in-progress
- **Draft changes are invisible until published** → Recent modifications won't appear until published

### Workflow for Agent Inspection:

1. **Extract `version_group_id`** (NOT `agent_id` or `id`) from the metadata
2. **Use the agents skill** to get the complete definition:
   ```bash
   cd ${CLAUDE_PLUGIN_ROOT}/skills/agents
   ../../scripts/python.sh scripts/agent_get.py --ids <version_group_id>
   ```
3. **Inspect the full definition** - review system prompt, tools, model, capabilities
4. **Only recommend/use** if the actual definition is a strong fit for the task

**Why:** Agent names and brief descriptions in the types list can be misleading. The actual system prompt, tool configuration, and capabilities determine if an agent is suitable. Don't guess based on names alone.

**Example - Correct vs Incorrect ID:**
```
Tool metadata shows:
  ID: agents/0ad0ec8a-c49a-4784-9541-8c931aa0a365/...  ← DON'T USE
  Version group: 4ff1fc7a-2181-405d-a6d7-95b549eb7a10    ← USE THIS

# ❌ WRONG:
agent_get.py --ids 0ad0ec8a-c49a-4784-9541-8c931aa0a365
# Returns: "failed to retrieve agent"

# ✅ CORRECT:
agent_get.py --ids 4ff1fc7a-2181-405d-a6d7-95b549eb7a10
# Returns: Full agent definition
```

## Script Reference

All scripts are nearly identical (just different paths):

| Script | Purpose | Endpoint |
|--------|---------|----------|
| `models_search.py` | Query available models | `/queries/models/v1` |
| `tools_search.py` | Query available tools | `/queries/tools/v1` |
| `templates_search.py` | Query agent templates | `/queries/agent-templates/v1` |
| `versions_search.py` | Query agent versions | `/queries/agent-versions/v1` |
| `spans_search.py` | Query trace spans (IDs only) | `/queries/spans/v1` |
| `spans_get.py` | Get full span entities | `/entities/spans/v1` |

## Usage Examples

### Query available models
```bash
../../scripts/python.sh scripts/models_search.py --limit 10
# Returns model IDs (UUIDs)
# NOTE: Filter only works by ID, not by name. Query all and filter client-side.
```

### Query tools by name or description
```bash
# DEPRECATED: tools_search.py uses /queries endpoint which may be unstable
# Use tools_get.py instead for client-side filtering

../../scripts/python.sh scripts/tools_get.py --search "logscale query" --verbose
# Searches across name, description, and category
# Automatically filters out overly-broad terms like "falcon", "crowdstrike"
# Returns full tool entities with descriptions

# Legacy approach (may return 500 errors):
../../scripts/python.sh scripts/tools_search.py --filter 'name:"logscale"' --limit 20
```

### Query tools by category

Use `tools_get.py --category` for an exact, case-sensitive category match. Prefer category
filtering when the requested capability maps to one of the families below; add `--search`
to narrow by name or description within that family.

```bash
../../scripts/python.sh scripts/tools_get.py \
  --category falcon_platform \
  --search "device query" \
  --limit 100
```

| Category | Use it to discover |
|----------|--------------------|
| `charlotte-mcp` | Curated Charlotte AI assistants for security tasks such as LogScale queries, detection triage, threat intelligence, malware analysis, documentation, and remediation guidance. |
| `agents` | Published Charlotte AI AgentWorks agents exposed as callable tools. Filter here when one agent should delegate a specialized task to another agent. |
| `gce` | Generic GCE tools, if present. This category currently returns no tools; do not confuse it with tool IDs prefixed `mcp/gce/`, whose actual categories are more specific. |
| `fusion_workflows` | On-demand Fusion workflow tools that execute a configured workflow and return its execution ID and declared outputs. |
| `falcon_platform` | First-party Falcon platform operations for hosts, detections, incidents, cases, identity, intelligence, LogScale, workflows, and response actions. |
| `integrations` | Operations supplied by configured third-party Fusion integrations; these commonly require an integration credential/configuration ID. |
| `Collections` | Create, get, list, search, and delete objects in agent-managed collections. The category name is case-sensitive. |
| `action_requests` | Human-in-the-loop actions that pause execution to request clarification. |
| `foundry-user-mcp` | Tools from user-configured MCP servers connected through Foundry, such as Jira, Confluence, Slack, or Microsoft documentation tools. Availability is tenant-specific. |

Category availability is tenant-specific. A zero-result category is not an error; report it
and only broaden the search after explaining that exact category matching found nothing.

**⚠️ IMPORTANT - Avoid Overly-Broad Search Terms:**
- ❌ DON'T search for: "falcon", "crowdstrike", "cs" (too generic, matches everything)
- ✅ DO search for: specific capabilities like "host search", "detections", "vulnerability", "logscale query"
- Think: "What unique capability am I looking for?" not "What product is this in?"

### Query agent templates
```bash
../../scripts/python.sh scripts/templates_search.py --filter 'category:"security"'
```

### Query agent versions
```bash
../../scripts/python.sh scripts/versions_search.py \
  --filter 'agent_id:"<agent-id>"' \
  --limit 10
```

### Query spans by trace ID
```bash
../../scripts/python.sh scripts/spans_search.py \
  --filter "trace_id:'abc123'+start_time:>='now-24h'" \
  --limit 100
# Note: Time filter required (start_time or end_time)
# Note: Use FQL syntax - operators are :>=, :<=, :<, :>, values in single quotes
```

### Query spans by agent ID
```bash
../../scripts/python.sh scripts/spans_search.py \
  --filter "(attributes.aw_agent.id:'<agent-id>'+start_time:>='now-7d')+span_type:['aw_agent','aw_eval_run_started']" \
  --limit 500
# Note: FQL uses + for AND, , for OR
# Note: Wrap complex filters in parentheses
# Note: Filter by span_type for efficiency (agent-level spans only)
```

### Hydrate span IDs to full entities
```bash
# First get span IDs from query (--json: the default output is a header plus an indented list)
SPAN_IDS=$(../../scripts/python.sh scripts/spans_search.py \
  --filter "trace_id:'abc123'+start_time:>='now-24h'" --json | jq -r '.resources[]')

# Then hydrate to full entities (SPAN_IDS is intentionally unquoted so each ID is its own argument)
../../scripts/python.sh scripts/spans_get.py --ids $SPAN_IDS
# Shows full span details: name, type, duration, status, credits, attributes
```

## Common Pitfalls

| Thought | Reality |
|---------|---------|
| "I'll use the agent ID from tool metadata to inspect it" | **Use version_group_id instead.** The `agent_id` field refers to a specific version. Use `version_group_id` to retrieve the current published definition. |
| "I just saw someone modify an agent, so inspection will show those changes" | **Modifications create drafts.** Agent inspection returns the latest **published** version, not draft versions. Changes are invisible until published. |
| "A tool ID beginning with `mcp/gce/` has category `gce`" | **ID namespace and category differ.** Filter the entity's exact category, such as `falcon_platform`, `fusion_workflows`, or `integrations`. |
| "Category matching ignores case" | **Treat categories as case-sensitive.** In particular, use `Collections` with a capital `C`. |
| "Discovery = get entities" | **Query IDs only (except `spans_get.py`).** Most scripts return IDs; use `GET /entities/...` to hydrate. |
| "Model name = model ID" | **Model ID is UUID.** Discovery returns IDs; filter only works by ID, not name. Query all models and grep client-side. |
| "I can filter models by name" | **Models filter only works by ID.** Query all (`--limit 100`) and filter client-side or use known model IDs. |
| "Span queries don't need time filters" | **Time filter REQUIRED.** The API enforces 90-day max age and adds default `start_time>=<90d-ago>` if missing. See `docs/SPAN_TIME_CONSTRAINTS.md` for full rules. |
| "I can query spans from 6 months ago" | **90-day hard limit.** Spans older than 90 days cannot be queried. Use `start_time:>=now-90d` for maximum history. |

## Reading Guide

| Task | Reference Doc |
|------|---------------|
| **FQL filter syntax (REQUIRED)** | `docs/FQL_SYNTAX_REFERENCE.md` |
| API endpoints and parameters | `references/api-reference.md` |
| FQL filter syntax | `references/fql-filters.md` |
| OAuth 2.0 + scopes | `../setup/SKILL.md` |
| **Span time constraints (CRITICAL)** | `docs/SPAN_TIME_CONSTRAINTS.md` |
| Span filter debugging | `docs/SPAN_FILTER_DEBUGGING.md` |

**Allowed (all read-only):**
- `GET /agentic-studio/queries/models/v1`
- `GET /agentic-studio/queries/tools/v1`
- `GET /agentic-studio/queries/agent-templates/v1`
- `GET /agentic-studio/queries/agent-versions/v1`
- `GET /agentic-studio/queries/spans/v1` (requires time filter)
- `GET /agentic-studio/entities/spans/v1` (hydrate span IDs)

Referenced files: 9 — file references are metadata, not package contents.

foundry-redirect3.34 KB

View saved version →

---
name: foundry-redirect
description: >
  TRIGGER when the user asks for an AI agent or knowledge base that lives inside a Falcon Foundry
  app: mentions "Foundry app", manifest.yml, the `ai.agents` or `ai.knowledge_bases` manifest
  blocks, `foundry agents create`, `foundry knowledge-bases create`, or exposing a collection or
  API operation as an agent tool. DO NOT TRIGGER for an agent or knowledge base created and managed
  directly through the Falcon API (no app, no manifest.yml); the agents and knowledge-bases skills
  own those. This skill declines Foundry-app requests and points to the crowdstrike-falcon-foundry
  plugin, so the redirect works even without plugin hooks; it yields to the real Foundry plugin
  when that plugin is also installed.
version: 1.0.1
updated: 2026-10-21
tags: [agentworks, foundry, redirect, routing]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
metadata:
  category: routing
---

# Falcon Foundry Redirect

If this skill triggered, the request is for an agent or knowledge base **inside a Falcon Foundry
app**, not one managed directly through the Falcon API. It belongs to the sibling Falcon Foundry
plugin. The `agentworks-skills` plugin creates and manages Charlotte AI AgentWorks agents through
the API only.

Why this skill exists: the `agents` and `knowledge-bases` skills decline Foundry-app requests too,
but their descriptions match API-management language, so a "add an agent to my Foundry app" prompt
may never load them. On Claude Code, Codex, Copilot CLI, and Cursor a hook covers that gap. On
assistants that do not load plugin hooks, this skill's description matches Foundry-app language
directly and makes the redirect reachable.

## What to do

Do NOT run the agents or knowledge-bases scripts. Do NOT write `ai.agents` or `ai.knowledge_bases`
manifest blocks yourself. Respond with all three:

1. State plainly that this request needs a Falcon Foundry app, not an API-managed AgentWorks agent.
2. Name the plugin: **`crowdstrike-falcon-foundry`**.
3. How to install it: `/plugin install crowdstrike-falcon-foundry` in Claude Code, `/plugins` in Codex, `copilot plugin install CrowdStrike/foundry-skills` in Copilot CLI, `/add-plugin crowdstrike-falcon-foundry` in Cursor, or clone https://github.com/CrowdStrike/foundry-skills.

## When both plugins are installed

If `crowdstrike-falcon-foundry` is present, its own `ai-agents-development` skill matches
Foundry-app agent requests directly and handles them, a stronger match than this one, so the agent
picks it and this redirect never fires. That is correct: this skill is the safety net for when the
Foundry plugin is absent, not a competitor with it when present.

## Foundry app agent vs. API-managed agent

| Signal in the request | Route |
|---|---|
| "Foundry app", `manifest.yml`, `ai.agents`, `ai.knowledge_bases`, `foundry agents create`, exposing a collection or API operation as an agent tool | **Here** — redirect to foundry-skills |
| "put my agent in Charlotte" from a Foundry app | **Here** — the app owns the agent; Foundry scaffolds and exposes it |
| Create, update, publish, or analyze an agent by ID or name against the Falcon API; manage a knowledge base and its files; invoke, cancel, or trace a run | **`agents`**, **`knowledge-bases`**, **`invocation`** — handle it here |
| Discover models, tools, templates, or spans | **`discovery`** — handle it here |
invocation15 KB

View saved version →

---
name: invocation
description: >
  Invoke Charlotte AI AgentWorks agents and manage invocations.
  Invoke published agents or specific versions, stream results, get messages, and cancel runs.
  Uses native FalconPy classes (`AgentInvocation`, `Stream`).
  TRIGGER when user asks to invoke an agent, run an agent, get agent results/messages, or cancel an invocation.
  DO NOT TRIGGER for agent creation (use agents skill), knowledge bases (use knowledge-bases skill),
  or discovery (use discovery skill).
version: 1.0.1
updated: 2026-10-21
tags: [agentworks, charlotte, invocation, streaming, falcon]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
allowed-tools: Bash(cd *), Bash(../../scripts/python.sh:*)
metadata:
  category: agent-execution
---

# Agent Invocation

> **Read this first.**
>
> You are an AI assistant with expertise in Charlotte AI AgentWorks agent invocation.
> Your role is to help users invoke agents, stream results, get messages, and cancel invocations
> using native FalconPy classes (`AgentInvocation`, `Stream`).
>
> **IMMEDIATE ACTIONS REQUIRED:**
> 1. Read this entire skill file before taking any action
> 2. Verify credentials are configured
> 3. Invoke **published agents** via `invoke_agent.py` OR **specific versions** (including drafts) via `invoke_version.py`
> 4. Run scripts via `cd ${CLAUDE_PLUGIN_ROOT}/skills/invocation && ../../scripts/python.sh scripts/<script>.py`
> 5. Parse script output and present results clearly
>
> **MUST NOT:**
> - Invoke unpublished agents using `invoke_agent.py` (will fail with 400) — use `invoke_version.py` instead
> - Guess invocation IDs — save from invoke response
> - Poll messages in tight loop (use reasonable intervals)

## Running the scripts

```bash
cd ${CLAUDE_PLUGIN_ROOT}/skills/invocation
../../scripts/python.sh scripts/<script_name>.py [args]
```

- **Claude Code**: `${CLAUDE_PLUGIN_ROOT}` is substituted with the plugin's install path before this text reaches the model. Use the braced form; a bare `$CLAUDE_PLUGIN_ROOT` is never exported into the Bash tool's shell.
- **Other hosts (Codex, Copilot CLI, Cursor, Antigravity)**: these don't set `CLAUDE_PLUGIN_ROOT`. `cd` to the folder you loaded this SKILL.md from (e.g. `~/.agents/skills/invocation`) and run `../../scripts/python.sh scripts/<script_name>.py [args]` from there.

## Prerequisites

- **Credentials**: Same as other skills
- **API scopes**: `csrn:charlotte-ai:agent:invocation` (assert/execute)
- **Agent publishing**:
  - `invoke_agent.py` requires **published agents** (invokes latest published version)
  - `invoke_version.py` can invoke **any version** (published or draft) by specifying version_id

## Core Workflow

1. **List recent invocations** → `list_invocations.py --agent-id <agent-id> --limit 10` → shows recent invocation IDs
2. **Invoke agent** → `invoke_agent.py --id <agent-id> --message "Hello"` → returns invocation_id and trace_id
   - **Optional controls**: `--deadline-seconds <seconds>` (min: 90), `--max-cost <credit-cents>` (100 = 1 credit; max: 10000, integer only) → constrain execution
3. **Get messages** → `get_messages.py --id <invocation-id> --wait` → blocks (backoff 5s→20s, default 300s timeout) until the invocation reaches a terminal status, then returns conversation messages. Add `--timeout <seconds>` to change the max wait. Omit `--wait` to just fetch the current state once, e.g. for a quick status check without blocking.
4. **Inspect trace** → `inspect_invocation.py --invocation-id <invocation-id>` → waterfall tree, duration, tool outputs
5. **Inspect cost** → Fetch the trace (discovery skill) and read `cost.agg_credit_cents`/`cost.raw_credit_cents` off its spans → actual cost in credit cents (no separate `cost` span_type -- see "Monitoring Invocation Costs" below)
6. **Stream invocation** → `stream_invocation.py --id <invocation-id>` → full conversation once complete (polls; not token-by-token SSE)
7. **Cancel invocation** → `cancel_invocation.py --id <invocation-id>` → stops in-flight run

## Invocation Controls

When invoking agents, you can optionally specify execution constraints:

### Deadline

Set a hard deadline (in seconds) after which the invocation will be terminated:

```bash
# Stop execution after 5 minutes (300 seconds)
../../scripts/python.sh scripts/invoke_agent.py \
  --id <agent-id> \
  --message "Your task..." \
  --deadline-seconds 300
```

**Constraints:**
- **Minimum value: 90 seconds** - Values below 90 are rejected with HTTP 400
- **Recommended minimum: 120 seconds** for agents with tool calls
- **Typical values**: 300-600 seconds for standard tasks, 900-1800 for complex operations

**Use cases:**
- Time-sensitive operations with hard cutoffs
- Preventing runaway agents from consuming excessive time
- Integration with external systems that have timeout constraints

### Max Cost

Set a maximum cost in Charlotte credit cents (100 = 1 Charlotte credit) to prevent expensive invocations:

```bash
# Limit invocation to 10,000 credit cents (100 Charlotte credits — the max allowed)
../../scripts/python.sh scripts/invoke_agent.py \
  --id <agent-id> \
  --message "Your task..." \
  --max-cost 10000
```

**Constraints:**
- **Maximum value: 10000 credit cents (100 Charlotte credits)** - Values above 10000 are rejected with HTTP 400
- **Must be an integer** - The API rejects non-integer values (e.g. `10000.0`) with a generic 400

**Credit Conversion:**
- **1 Charlotte credit = 100 credit cents**
- Example values:
  - `--max-cost 100` = 1 Charlotte credit
  - `--max-cost 1000` = 10 Charlotte credits
  - `--max-cost 10000` = 100 Charlotte credits (the maximum allowed)

**Use cases:**
- Budget control for exploratory or experimental agents
- Cost caps for user-facing agents in multi-tenant environments
- Preventing unexpectedly expensive tool calls or excessive LLM usage

### Combined Controls

Both parameters can be used together:

```bash
../../scripts/python.sh scripts/invoke_agent.py \
  --id <agent-id> \
  --message "Analyze recent detections" \
  --deadline-seconds 600 \
  --max-cost 10000
```

**Behavior when limits are reached:**
- The invocation is terminated gracefully
- Partial results (if any) are available via `get_messages.py`
- Trace shows termination reason in span attributes

**Note:** `max_cost` is expressed in **credit cents** where 100 = 1 Charlotte credit, capped at 10000 (100 Charlotte credits).

### Monitoring Invocation Costs

After an invocation completes, you can inspect the actual cost incurred by fetching the
trace and reading its `cost.*` attributes -- there is no separate `cost` span_type; cost
lives directly on the spans a normal trace query already returns (confirmed against a live
tenant, 2026-09-23):

```bash
# Get the trace_id from the invocation response, then fetch the full trace.
cd ${CLAUDE_PLUGIN_ROOT}/skills/discovery
../../scripts/python.sh scripts/spans_search.py \
  --filter "trace_id:'<trace-id>'+start_time:>='now-24h'" \
  --limit 500
# Hydrate the returned span IDs with spans_get.py, then read cost.* off the
# aw_agent_response / llm spans (see below) -- no additional filter needed.
```

**Cost attributes (on `aw_agent_response`/`llm` spans):**
- `cost.agg_credit_cents` — total cost for the whole invocation (on the `aw_agent_response` span)
- `cost.raw_credit_cents` — per-LLM-call cost (on individual `llm` spans)
- `cost.reserved_credit_cents` — the budget that was *reserved* for the invocation, not what
  was actually spent (confirmed live: on a failed/timed-out invocation, `agg_credit_cents`
  was `0` while `reserved_credit_cents` still showed the reserved amount) -- don't mistake it
  for actual cost.
- `cost.was_quota_consumed` — whether the invocation was charged against quota vs. credits

**Use cases:**
- Verify actual cost vs. budget after invocation completes
- Analyze cost trends across multiple invocations
- Identify expensive agents or operations for optimization
- Generate cost reports for billing/accounting

## Script Reference

| Script | Purpose | Key Flags |
|--------|---------|-----------|
| `list_invocations.py` | List recent invocations for an agent | `--agent-id <uuid>`, `--limit 10`, `--days 7` |
| `invoke_agent.py` | Invoke latest **published** version of an agent | `--id <agent-id>`, `--message "..."`, `--deadline-seconds <seconds>` (min: 90), `--max-cost <credit-cents>` (100 = 1 credit; max: 10000, integer only) |
| `invoke_version.py` | Invoke **specific version** (published or draft) | `--agent-id`, `--version-id <uuid>`, `--message`, `--deadline-seconds`, `--max-cost` — returns `invocation_id`; feed that straight into `inspect_invocation.py --invocation-id` (it resolves its own `trace_id`) |
| `get_messages.py` | Get conversation from invocation | `--id <invocation-id>`, `--wait` (block until terminal status, backoff 5s→20s), `--timeout <seconds>` (default 300, only with `--wait`) |
| `inspect_invocation.py` | Inspect invocation trace (waterfall + tool outputs) | `--invocation-id` (required), `--tool-output-only`, `--errors-only` (only show tool spans that errored), `--json` |
| `cancel_invocation.py` | Cancel in-flight invocation | `--id <invocation-id>` |
| `stream_invocation.py` | Stream invocation results (polls; returns full conversation) | `--id <invocation-id>` |

## Usage Examples

### List recent invocations for an agent
```bash
../../scripts/python.sh scripts/list_invocations.py \
  --agent-id <agent-id> \
  --limit 10

# Shows:
# - Invocation IDs
# - Timestamps
# - Duration
# - Status (✅ success / ❌ error)
# - Span count
```

### Invoke a published agent
```bash
../../scripts/python.sh scripts/invoke_agent.py \
  --id <agent-id> \
  --message "Investigate detection XYZ for unauthorized access"
# Returns: invocation_id and trace_id
# Use invocation_id with inspect_invocation.py to view execution details
```

**With execution controls:**
```bash
# With deadline (minimum 90 seconds)
../../scripts/python.sh scripts/invoke_agent.py \
  --id <agent-id> \
  --message "Investigate detection XYZ" \
  --deadline-seconds 300

# With max cost (credit cents: 100 = 1 Charlotte credit)
../../scripts/python.sh scripts/invoke_agent.py \
  --id <agent-id> \
  --message "Analyze vulnerabilities" \
  --max-cost 10000

# With both
../../scripts/python.sh scripts/invoke_agent.py \
  --id <agent-id> \
  --message "Comprehensive security audit" \
  --deadline-seconds 900 \
  --max-cost 10000
```

### Invoke a specific version (draft or published), then inspect its trace
```bash
../../scripts/python.sh scripts/invoke_version.py \
  --agent-id <agent-id> \
  --version-id <version-id> \
  --message "Investigate detection XYZ"
# Returns: invocation_id (no trace_id printed directly -- inspect_invocation.py
# resolves its own trace_id from the invocation_id, so this is enough)

../../scripts/python.sh scripts/get_messages.py --id <invocation-id> --wait
# Blocks until the invocation reaches a terminal status

../../scripts/python.sh scripts/inspect_invocation.py --invocation-id <invocation-id>
# Waterfall + tool outputs for this specific version's run
```

### Get invocation messages
```bash
../../scripts/python.sh scripts/get_messages.py \
  --id abc123-invocation-id
```

### Inspect full trace (waterfall + tool outputs)
```bash
../../scripts/python.sh scripts/inspect_invocation.py \
  --invocation-id abc123-invocation-id

# Shows:
# - Waterfall tree visualization
# - Total invocation duration
# - Per-span durations
# - Tool outputs with attributes
```

### Inspect invocation cost
```bash
# First, get the trace_id from the invocation (returned by invoke_agent.py)
TRACE_ID="<trace-id-from-invocation>"

# Fetch the full trace using the discovery skill -- cost lives in attributes
# on the spans this already returns, there is no separate "cost" span_type.
cd ${CLAUDE_PLUGIN_ROOT}/skills/discovery
../../scripts/python.sh scripts/spans_search.py \
  --filter "trace_id:'${TRACE_ID}'+start_time:>='now-24h'" \
  --limit 500

# Hydrate the returned span IDs, then read cost.agg_credit_cents off the
# aw_agent_response span (total) or cost.raw_credit_cents off individual
# llm spans (per-call):
../../scripts/python.sh scripts/spans_get.py --ids <span-id>

# Shows:
# - Total cost in credit cents
# - Cost breakdown by resource type
# - Model-specific costs
# - Token usage metrics
```

### Inspect only tool outputs
```bash
../../scripts/python.sh scripts/inspect_invocation.py \
  --invocation-id abc123-invocation-id \
  --tool-output-only
```

### Cancel running invocation
```bash
../../scripts/python.sh scripts/cancel_invocation.py \
  --id abc123-invocation-id
```

### Stream invocation results
```bash
../../scripts/python.sh scripts/stream_invocation.py \
  --id abc123-invocation-id
# Note: FalconPy limitation - returns full conversation after completion, not true SSE
```

## Common Pitfalls / Counter-Rationalizations

| Thought | Reality |
|---------|---------|
| "I'll invoke the draft agent with invoke_agent.py" | **Use invoke_version.py for drafts.** `invoke_agent.py` only invokes the latest **published** version. To test draft/unpublished versions, use `invoke_version.py --agent-id <id> --version-id <version-uuid>`. |
| "I need a :draft-invocation scope to invoke drafts" | **No special scope needed.** The base `:invocation` scope covers both published and draft version invocations. Use `invoke_version.py` with the draft's version_id. |
| "I'll set a deadline 30 seconds from now for a complex task" | **Minimum 90 seconds required.** The API rejects `deadline_seconds` values below 90 with HTTP 400. Set realistic deadlines: 120+ for simple tasks, 300-600 for standard operations, 900+ for complex workflows. |
| "Max cost is just a suggestion" | **Max cost is a hard limit.** The invocation terminates when the limit (in credit cents: 100 = 1 Charlotte credit) is reached. Set appropriate budgets or omit the parameter for unbounded execution. |
| "I can pass any value for --max-cost" | **Capped at 10000 and integer-only.** The API rejects values above 10000 credit cents (100 Charlotte credits) with a 400, and rejects non-integer values (e.g. `10000.0`) with a generic "invalid ... invocation request" error. |
| "Cost is in the invocation response" | **Cost is in trace span attributes.** Fetch the trace (discovery skill) and read `cost.agg_credit_cents`/`cost.raw_credit_cents` off its spans -- there's no separate `cost` span_type. The invocation response doesn't include cost data. |
| "I can see costs in get_messages output" | **Cost is on the trace's spans.** Use the discovery skill to fetch the trace_id's spans and read `cost.*` attributes. Messages don't contain cost information. |
| "Invocation ID = agent ID" | **Different UUIDs.** Invocation ID is returned from invoke call; don't reuse agent ID. |
| "I'll poll messages every 100ms" | **Rate limit risk.** Use reasonable intervals (1-5s) or use streaming. |
| "Streaming uses /agentic-studio base" | **Wrong base.** Streaming uses `/agentic-studio-streaming/` base path. |
| "Tool outputs are in messages" | **Tool outputs are in trace spans.** Use `inspect_invocation.py` to see invocation waterfall, duration, and raw tool outputs. |
| "I need a dedicated endpoint to list invocations" | **Use spans APIs.** Query spans by `agent_id`, extract `invocation_id` from attributes. Use `list_invocations.py`. |

Referenced files: 7 — file references are metadata, not package contents.

knowledge-bases9.79 KB

View saved version →

---
name: knowledge-bases
description: >
  Manage Charlotte AI AgentWorks knowledge bases.
  Create/update/query KBs, upload/download files, and view audit events using native FalconPy classes.
  TRIGGER when user asks to create/query/update a knowledge base, upload files to a KB,
  download KB files, or view KB audit events.
  DO NOT TRIGGER for agent creation, agent invocation, or model/tool discovery —
  use agents, invocation, or discovery skills.
  DO NOT TRIGGER for knowledge bases defined in a Falcon Foundry app (manifest.yml `ai.knowledge_bases`,
  `foundry knowledge-bases create`); foundry-redirect handles those.
version: 1.0.1
updated: 2026-10-21
tags: [agentworks, charlotte, knowledge-base, files, audit, falcon]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
allowed-tools: Bash(cd *), Bash(../../scripts/python.sh:*)
metadata:
  category: data-management
---

# Knowledge Bases

> **Read this first.**
>
> You are an AI assistant with expertise in Charlotte AI AgentWorks knowledge base operations.
> Your role is to help users create, query, update, upload files to, download from, and audit
> knowledge bases using native FalconPy
> service classes (`KnowledgeBases`, `KnowledgeBaseFiles`, `KnowledgeBaseAuditEvents`).
>
> **IMMEDIATE ACTIONS REQUIRED:**
> 1. Read this entire skill file before taking any action
> 2. Verify credentials are configured (TOML profile or env vars)
> 3. Only use the scripts documented below — never guess API parameters
> 4. Run scripts via `cd ${CLAUDE_PLUGIN_ROOT}/skills/knowledge-bases && ../../scripts/python.sh scripts/<script>.py`
> 5. Parse script output and present results clearly to the user
>
> **MUST NOT:**
> - Delete KBs or files (delete operations excluded from v1 scope)
> - Guess knowledge_base_id or file IDs — always query first

## Running the scripts

All scripts must be invoked through the managed venv wrapper so dependencies (FalconPy) are available:

```bash
cd ${CLAUDE_PLUGIN_ROOT}/skills/knowledge-bases
../../scripts/python.sh scripts/<script_name>.py [args]
```

- **Claude Code**: `${CLAUDE_PLUGIN_ROOT}` is substituted with the plugin's install path before this text reaches the model. Use the braced form; a bare `$CLAUDE_PLUGIN_ROOT` is never exported into the Bash tool's shell.
- **Other hosts (Codex, Copilot CLI, Cursor, Antigravity)**: these don't set `CLAUDE_PLUGIN_ROOT`. `cd` to the folder you loaded this SKILL.md from (e.g. `~/.agents/skills/knowledge-bases`) and run `../../scripts/python.sh scripts/<script_name>.py [args]` from there.

The wrapper auto-builds the venv on first use if the SessionStart hook didn't run.

## Prerequisites

- **Credentials**: Charlotte AI AgentWorks TOML (`~/.cache/crowdstrike-charlotte-ai-agentworks/credentials.toml`) OR env vars (`FALCON_CLIENT_ID`, `FALCON_CLIENT_SECRET`, optional `FALCON_BASE_URL`). Run `/crowdstrike-charlotte-ai-agentworks:setup` if needed.
- **API scopes**: `csrn:charlotte-ai:agent:knowledge-base` (read + write)
- **Python 3.14+**: Auto-managed by the venv setup
- **FalconPy 1.6.6+**: Provides the native `KnowledgeBases`, `KnowledgeBaseFiles`, `KnowledgeBaseAuditEvents` classes (`common/scripts/auth.py` enforces a shared 1.6.6+ floor across all skills)

## Core Workflow

1. **Search/browse KBs by name or description substring** → `kb_list.py --contains "topic"` → table of matches, no exact-syntax guessing needed
2. **Query KB IDs by exact/known filter** → `kb_search.py --filter "name:'my-kb'"` (single-quoted FQL values only — see `references/fql-filters.md`) → returns KB IDs
3. **Get KB details** → `kb_get.py --ids <id1> <id2>` → full KB entities
4. **Create or update KB** → `kb_upsert.py --name "..." --description "..."` (optional `--id` for update)
5. **Upload file** → `kb_file_upload.py --kb-id <id> --file <path> --description "..."`
6. **List/browse files in a KB** → `kb_files_list.py --kb-id <id>` → table of files with size, type, status
7. **Download file** → `kb_file_download.py --kb-id <id> --file-id <id> --output <path>`
8. **View audit events** → `kb_audit.py --kb-id <id> --limit 50`

Stop after each script; confirm with user before proceeding to the next step.

## Script Reference

| Script | Purpose | Key Flags |
|--------|---------|-----------|
| `kb_list.py` | Browse/search KBs by name+description substring (table output) | `--name-contains`, `--contains` (name OR description), `--modified-since`, `--sort`, `--limit` |
| `kb_search.py` | Query KB IDs by exact/known FQL filter | `--filter "name:'...'"` (single-quoted!), `--limit 100` |
| `kb_get.py` | Get KB entities by IDs | `--ids <id> [id...]` |
| `kb_upsert.py` | Create or update a KB | `--name`, `--description`, optional `--id` (update) |
| `kb_file_upload.py` | Upload file to a KB | `--kb-id`, `--file <path>`, `--description` |
| `kb_files_list.py` | List files in a KB (table output) | `--kb-id`, `--name-contains` |
| `kb_file_download.py` | Download file from KB | `--kb-id`, `--file-id`, `--output <path>` |
| `kb_audit.py` | Query KB audit events | `--kb-id`, `--limit 100` |

All scripts support `--help` for full arg lists and `--json` for raw JSON output.

**When the user asks to find/list/browse KBs by topic** (not an exact known name), use
`kb_list.py --contains "topic"`, not `kb_search.py`. `kb_search.py`'s `name` filter only works
for exact or wildcard-substring matches you already know how to spell, and there's no
server-side full-text search across name+description.

## Usage Examples

### Search/browse KBs by topic
```bash
../../scripts/python.sh scripts/kb_list.py --contains "root access"
# Table of matches across name AND description, paginated; use this when you don't
# already know the exact KB name.
```

### Query KBs by exact name
```bash
../../scripts/python.sh scripts/kb_search.py --filter "name:'Insurance'" --limit 10
# Returns KB IDs. Values MUST be single-quoted -- name:"Insurance" silently matches nothing.
```

### Get KB details
```bash
../../scripts/python.sh scripts/kb_get.py --ids abc123-kb-id
```

### Create a new KB
```bash
../../scripts/python.sh scripts/kb_upsert.py \
  --name "Insurance Terms & Conditions" \
  --description "Romanian insurance policy documentation"
# Returns KB ID
```

### Update existing KB
```bash
../../scripts/python.sh scripts/kb_upsert.py \
  --id abc123-kb-id \
  --description "Updated description..."
```

### Upload file to KB
```bash
../../scripts/python.sh scripts/kb_file_upload.py \
  --kb-id abc123-kb-id \
  --file /path/to/document.pdf \
  --description "Insurance policy terms"
# Returns file ID
```

### List files in a KB
```bash
../../scripts/python.sh scripts/kb_files_list.py --kb-id abc123-kb-id
# Table: name, description, size, content type, status, last modified, modified by, file ID
```

### Download file from KB
```bash
../../scripts/python.sh scripts/kb_file_download.py \
  --kb-id abc123-kb-id \
  --file-id file123 \
  --output ./downloaded-policy.pdf
```

### View KB audit events
```bash
../../scripts/python.sh scripts/kb_audit.py \
  --kb-id abc123-kb-id \
  --limit 50
# Shows file uploads, KB updates, etc.
```

### Attach KB to agent (see agents skill)
```bash
cd ../agents
../../scripts/python.sh scripts/agent_upsert.py \
  --id <agent-id> \
  --knowledge-base-ids abc123-kb-id
```

## Common Pitfalls / Counter-Rationalizations

| Thought | Reality |
|---------|---------|
| "I'll guess the KB ID" | **Query first.** KB IDs are UUIDs; guessing fails 100%. Use `kb_search.py` or `kb_list.py`. |
| "I'll skip the filter and list all KBs" | **Always filter.** Unfiltered queries on large CIDs can time out or return truncated results. Use `--filter "name:'...'"` or a date range, or use `kb_list.py` which paginates for you. |
| "`--filter 'name:\"my-kb\"'` with double quotes should work" | **Silently wrong.** FQL string values must be single-quoted (`name:'my-kb'`). Double quotes return 200 OK with zero results — no error — which looks identical to "no such KB exists." See `references/fql-filters.md`. |
| "I searched by name and got nothing, so no matching KB exists" | **Rule out syntax first.** `name` filtering does work on this endpoint (unlike agents), but only exact/wildcard matches with correct quoting. Before concluding nothing exists, either fix the quoting or use `kb_list.py --contains "..."` for substring search across name+description. |
| "File upload is just POST + JSON body" | **Multipart/form-data required.** `kb_file_upload.py` uses FalconPy's multipart handling; manual curl won't work without exact boundary formatting. |
| "I can delete a KB by setting is_deleted:true" | **Delete out of scope.** Per v1 plan, no delete operations. KBs persist once created. |
| "I'll list a KB's files with `kb_search.py --kb-id`" | **That flag doesn't exist.** Use `kb_files_list.py --kb-id <id>` instead. |
| "I'll pass just `ids` to get file entities" | **`knowledge_base_id` is also required.** `EntitiesKnowledgeBaseFilesV1(ids=[...])` alone fails with "knowledge_base_id parameter is required" — pass both, e.g. `EntitiesKnowledgeBaseFilesV1(knowledge_base_id=kb_id, ids=[...])`. Matches what the Falcon UI itself sends. |
| "The native FalconPy class means I don't need auth.py" | **Auth.py is required.** It builds the clients with credential resolution. Never instantiate `KnowledgeBases()` directly in scripts. |

## Reading Guide

For deep dives, see `references/`:

| Task | Reference Doc |
|------|---------------|
| Full endpoint table (methods, paths, params) | `references/api-reference.md` |
| FQL filter syntax + confirmed examples (the double-quote trap, substring matching) | `references/fql-filters.md` |
| OAuth 2.0 flow + scope requirements | `../setup/SKILL.md` |

Load these on demand — don't read upfront.

## FalconPy Native Support

This skill uses **native typed FalconPy service classes**. Benefits:
- Typed methods: `client.EntitiesKnowledgeBasesCreateV1(body={...})`
- Auto-parameter validation
- Built-in pagination + error handling


Referenced files: 10 — file references are metadata, not package contents.

setup4.92 KB

View saved version →

---
name: setup
description: >
  Configure credentials for Charlotte AI AgentWorks API access. Guides users through manual TOML
  configuration or environment variable setup.
  TRIGGER when user explicitly asks to "set up Charlotte AI AgentWorks", "configure credentials", or has auth errors.
  DO NOT TRIGGER for general Charlotte AI AgentWorks usage (orchestrator handles routing).
version: 1.0.1
updated: 2026-10-21
tags: [agentworks, setup, credentials, authentication]
author: CrowdStrike
license: MIT
compatibility: Claude Code >=1.0
metadata:
  category: configuration
---

# Charlotte AI AgentWorks Setup

## Configuration

This plugin requires Falcon API OAuth 2.0 credentials. Configure using one of the methods below.

**Test authentication:**
```bash
scripts/python.sh common/scripts/auth.py
```

Should authenticate 5 FalconPy clients (KnowledgeBases, KnowledgeBaseFiles, KnowledgeBaseAuditEvents, Agents, AgentInvocation), all sharing one token.

## Setup Methods

### Option 1: TOML Profile (Recommended)

Create `~/.cache/crowdstrike-charlotte-ai-agentworks/credentials.toml`:

```toml
default = "us-1"

[us-1]
client_id = "your-client-id-here"
client_secret = "your-client-secret-here"
base_url = "https://api.crowdstrike.com"  # or your cloud URL
```

Set permissions:
```bash
mkdir -p ~/.cache/crowdstrike-charlotte-ai-agentworks
chmod 700 ~/.cache/crowdstrike-charlotte-ai-agentworks
chmod 600 ~/.cache/crowdstrike-charlotte-ai-agentworks/credentials.toml
```

### Option 2: Environment Variables

```bash
export FALCON_CLIENT_ID=<your-id>
export FALCON_CLIENT_SECRET=<your-secret>
export FALCON_BASE_URL=https://api.crowdstrike.com  # optional, defaults to US-1
```

## Required API CSRN Permissions

Charlotte AI AgentWorks uses these CSRN permissions:
- `csrn:charlotte-ai:agent:definition` (read + write)
- `csrn:charlotte-ai:agent:invocation` (assert/execute)
- `csrn:charlotte-ai:agent:knowledge-base` (read + write)
- `csrn:charlotte-ai:agent:template` (read)
- `csrn:charlotte-ai:agent:metrics` (read)

## Verification

After setup, run:
```bash
cd /path/to/agentworks-skills
scripts/python.sh common/scripts/auth.py
```

Should see:
```
✓ Authentication successful (KnowledgeBases client)
✓ Authentication successful (KnowledgeBaseFiles client)
✓ Authentication successful (KnowledgeBaseAuditEvents client)
✓ Authentication successful (Agents client)
✓ Authentication successful (AgentInvocation client)
```

## Troubleshooting

**"No credentials found"**
- Check TOML file exists and has correct profile
- OR set env vars

**"Authentication FAILED"**
- Verify client_id/secret are correct
- Check base_url matches your Falcon cloud (us-1, us-2, eu-1, etc.)
- Ensure API client has required scopes

**"token_expired() returns True"**
- Check network connectivity to Falcon API
- Verify client_id/secret haven't been rotated
- Run `python common/scripts/auth.py` -- as of this version it prints the real API error
  (e.g. bad credentials, missing scope) instead of just "could not obtain token"

**Authentication fails with a certificate/TLS error during login** (e.g.
`CERTIFICATE_VERIFY_FAILED: unable to get local issuer certificate`) -- distinct from the
package-install certificate errors below; this happens on the live API call itself, often
behind a TLS-intercepting proxy (e.g. Zscaler) common in corporate environments.
- Check whether your organization requires a custom CA bundle for outbound HTTPS, and that
  Python's trust store (or `SSL_CERT_FILE`/`REQUESTS_CA_BUNDLE`) points at it
- Confirm a plain `curl` to your `base_url` succeeds from the same shell/environment first --
  if that also fails, this is a network/proxy config issue outside the plugin, not an
  Charlotte AI AgentWorks credential problem
- These settings must be configured outside the AI coding agent; restart the coding agent
  terminal after configuring so it receives the updated environment

**Package installation reports access, certificate, or registry errors**
- Refer the user to their organization's documentation for setting up a Python environment.
- Their organization may require an approved package registry or specific certificates.
- These settings must be configured outside the AI coding agent.
- After configuration, restart the coding agent terminal so it receives the updated environment.
- Some workstation changes may require signing out and back in before restarting the agent.

## Security

- **Never paste credentials into chat**
- Credentials go only into the TOML file (via your editor) or env vars
- TOML file should be `chmod 600`
- TOML directory should be `chmod 700`
- Never commit credentials to git

## Multi-Cloud Support

Charlotte AI AgentWorks supports all Falcon clouds. `base_url` may be any Falcon cloud URL,
including custom/internal environments; it is not restricted to this list:
- US-1: `https://api.crowdstrike.com` (default)
- US-2: `https://api.us-2.crowdstrike.com`
- EU-1: `https://api.eu-1.crowdstrike.com`
- US-GOV-1: `https://api.laggar.gcw.crowdstrike.com`
Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package license
MIT
Package author
CrowdStrike
Keywords
See keywords

Declared capabilities

  • Interactive
  • Write

Package observed Nov 3, 2026.

Technical details
First seen
Oct 26, 2026 · 12:00 UTC
Last seen
Nov 4, 2026 · 06:00 UTC
Collection status
Collected

plugins_6acdf14f94488191ae8c3425230d7ab0

Download plugin data (JSON)