> ## Documentation Index
> Fetch the complete documentation index at: https://docs.greenflash.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Logging System Prompts (Python)

> System prompt for coding agents to upgrade an existing Python SDK integration to log system prompts for prompt optimization. Copy and paste the content of this page into your coding assistant.

export const CopyAllButton = ({content, label = 'Copy Page'}) => {
  const [copied, setCopied] = React.useState(false);
  const handleCopy = async () => {
    try {
      await navigator.clipboard.writeText(content);
      setCopied(true);
      setTimeout(() => setCopied(false), 3000);
    } catch (err) {
      console.error('Failed to copy content:', err);
      alert('Failed to copy content. Please try selecting and copying manually.');
    }
  };
  return <div className="copy-all-container">
      <div className="copy-all-content">
        <div className="copy-all-title">Copy Integration Instructions</div>
        <div className="copy-all-description">
          Click to copy the entire page content to paste into your AI coding
          assistant
        </div>
      </div>
      <button className={`copy-all-button${copied ? ' copied' : ''}`} onClick={handleCopy} type="button">
        {copied ? 'Page Copied' : label}
      </button>
    </div>;
};

<Tip>
  **Using a Skills-compatible agent like Claude Code?** The [Greenflash agent skill](/features/agent-skill) handles this automatically. Run `/greenflash-onboard-prompts` instead of copying this prompt.
</Tip>

export const pageContent = `# Upgrade an Existing Python SDK Integration to Log System Prompts

You are a **coding agent** tasked with updating our existing Python SDK integration with the **Greenflash Messages API** so that it correctly logs **system prompts** for **prompt optimization & management**. We already have a working integration but are not currently submitting any system prompts alongside messages. Your goal is to **enhance our integration** so that Greenflash can automatically version, analyze, and optimize system prompts based on real conversation data.

---

## High-Level Objective

Refactor or extend the existing implementation to:

1. **Include system prompts** when logging conversations
2. **Support both simple string prompts and structured \\\`promptComponents\\\`**
3. **Ensure dynamic and variable content in complex prompts is logged properly**
4. **Use the correct Python SDK syntax**
5. **Determine the right logging pattern** (batch vs individual calls) based on how the existing code is written

This is not a correction of our current setup; it is an **evolution** toward richer analytic and optimization tooling.

---

## Logging System Prompts: Two Valid Formats

Greenflash supports **two ways** to include a system prompt when logging a conversation. You must choose between them based on the complexity of the prompt being submitted.

### Option A: Simple String Prompt

Use this when the system prompt is a *single static string*.

**Sync:**

\\\`\\\`\\\`python
client.messages.create(
    external_user_id=...,
    external_conversation_id=...,
    product_id=...,
    system_prompt="You are a helpful assistant. Be concise and friendly.",
    messages=[ ... ],
)
\\\`\\\`\\\`

**Async (fire-and-forget):**

\\\`\\\`\\\`python
asyncio.create_task(client.messages.create(
    external_user_id=...,
    external_conversation_id=...,
    product_id=...,
    system_prompt="You are a helpful assistant. Be concise and friendly.",
    messages=[ ... ],
))
\\\`\\\`\\\`

**Pros:**

- Easy to implement
- Automatically gets tracked & versioned
- Good for most use cases

**Cons:**

- Cannot express structured or dynamic prompts
- Less granular optimization

Use this when prompts are simple, static strings.

### Option B: Structured Prompt with promptComponents

Use this when the prompt includes multiple pieces, variables, dynamic slots, templates, or RAG context elements. A structured prompt lets you segment instructions into named components, version them independently, and optimize at the component level.

\\\`\\\`\\\`python
system_prompt = {
    "external_template_id": "my-assistant-prompt",
    "components": [
        {
            "type": "system",
            "name": "base_instructions",
            "content": "You are a customer support assistant for {{company}}."
        },
        {
            "type": "system",
            "name": "tone_guidelines",
            "content": "Always be professional and empathetic."
        },
        {
            "type": "rag",
            "name": "context",
            "content": dynamic_rag_text,
            "isDynamic": True
        }
    ],
    "variables": {
        "customerName": customer_name,
        "company": company_name
    }
}

# Sync
client.messages.create(
    external_user_id=...,
    external_conversation_id=...,
    product_id=...,
    system_prompt=system_prompt,
    messages=[ ... ],
)

# Async (fire-and-forget)
asyncio.create_task(client.messages.create(
    external_user_id=...,
    external_conversation_id=...,
    product_id=...,
    system_prompt=system_prompt,
    messages=[ ... ],
))
\\\`\\\`\\\`

**Key Notes for Structured Prompts:**

- **\\\`external_template_id\\\`** groups all versions of this prompt under a single lineage. Use a stable, human-readable identifier (e.g., \\\`"customer-support-agent"\\\`). Without this, each unique prompt creates a separate lineage.
- Valid component **\\\`type\\\`** values: \\\`system\\\`, \\\`user\\\`, \\\`tool\\\`, \\\`guardrail\\\`, \\\`rag\\\`, \\\`agent\\\`, \\\`other\\\`. Each component can also have a **\\\`source\\\`**: \\\`customer\\\` (default), \\\`participant\\\`, \\\`greenflash\\\`, or \\\`agent\\\`.
- Use \\\`isDynamic: True\\\` for parts of the prompt that vary per conversation (e.g., retrieved context, dynamic instructions)
- Use \\\`variables\\\` on the system_prompt object to pass template variable values (e.g., \\\`{{companyName}}\\\`)

**Advantages:**

- Modular prompt structure
- Component-level optimization
- Variable interpolation
- Dynamic content slots for RAG or agent outputs

Use this when prompts are complex, have templates, or contain dynamic data.

---

## Async vs Sync Considerations

When adding system prompt logging, match our existing async/sync pattern:

- **Sync apps:** Call \\\`client.messages.create(...)\\\` directly. Use the sync \\\`Greenflash\\\` client.
- **Async apps:** Use \\\`AsyncGreenflash\\\` and wrap calls in \\\`asyncio.create_task()\\\` for fire-and-forget logging that won't block our LLM responses.

> **Important:** In Python, calling an async function without \\\`await\\\` returns a coroutine that never executes. Always use \\\`asyncio.create_task()\\\` for fire-and-forget patterns in async code.

---

## Detecting the Right Pattern

Inspect the existing codebase and choose the pattern that minimally disrupts current logic:

- If prompts are static strings and there is no variable logic or dynamic content, use **Simple String Format**
- If prompts are assembled from pieces, templates, or dynamic slots, use **Structured Prompt with Components**
- If code emits prompt text dynamically as it runs, wrap that logic into structured components with \\\`isDynamic: True\\\` where needed

Once the pattern is chosen, update the logging logic accordingly.

---

## Logging Messages with Prompts

After adding the system prompt, the rest of the messages follow the existing logging pattern:

- You may send all messages in a batch if they are known at the end of execution
- Or you may log messages incrementally as they happen (e.g., streaming)
- Use \\\`client.messages.create(...)\\\` for each call when logging incrementally
- For batch mode, send a single call with \\\`system_prompt\\\` and message array

Either approach is valid — choose what aligns best with the existing code flow.

---

## Python SDK Integration Checklist

Your code should:

1. **Initialize the Python SDK** with our API key (use \\\`Greenflash\\\` for sync, \\\`AsyncGreenflash\\\` for async)
2. **Construct \\\`system_prompt\\\`**:
   - As a simple string, or
   - As a structured object with \\\`promptComponents\\\`
3. **Include \\\`system_prompt\\\`** on every \\\`messages.create(...)\\\` call
4. **Respect dynamic variables** using \\\`variables\\\` on the system_prompt object if structured prompts have templates
5. **Choose batching vs streaming** appropriately
6. **Preserve existing logging semantics** for message bodies
7. **Use \\\`asyncio.create_task()\\\`** for fire-and-forget logging in async code

**Example with variables (sync):**

\\\`\\\`\\\`python
system_prompt_with_vars = {
    "external_template_id": "my-assistant-prompt",
    "components": [# your prompt components],
    "variables": {
        "userName": user_name,
        "companyName": company_name
    }
}

client.messages.create(
    external_user_id=user_id,
    external_conversation_id=conversation_id,
    product_id=product_id,
    system_prompt=system_prompt_with_vars,
    messages=message_list,
)
\\\`\\\`\\\`

**Example with variables (async fire-and-forget):**

\\\`\\\`\\\`python
system_prompt_with_vars = {
    "external_template_id": "my-assistant-prompt",
    "components": [# your prompt components],
    "variables": {
        "userName": user_name,
        "companyName": company_name
    }
}

asyncio.create_task(client.messages.create(
    external_user_id=user_id,
    external_conversation_id=conversation_id,
    product_id=product_id,
    system_prompt=system_prompt_with_vars,
    messages=message_list,
))
\\\`\\\`\\\`

---

## Tips

- **String prompts** are great to start with and will get metrics and analytics immediately
- **Structured prompts** unlock component-level optimization and versioning
- **Dynamic components** (\\\`isDynamic: True\\\`) allow RAG and other runtime context to be logged correctly
- **Interpolated variables** let you keep templates generic while capturing personalized conversation data

---

## Summary of What to Deliver

- Updated Python SDK integration that logs system prompts
- Support for both simple string prompts and structured prompt components
- Logic to choose the right pattern
- Ensure dynamic data and variables are logged properly
- No disruption to existing message logging behavior

This will unlock Greenflash's prompt optimization capabilities across our AI products.`;

<CopyAllButton content={pageContent} />

# Upgrade an Existing Python SDK Integration to Log System Prompts

You are a **coding agent** tasked with updating our existing Python SDK integration with the **Greenflash Messages API** so that it correctly logs **system prompts** for **prompt optimization & management**. We already have a working integration but are not currently submitting any system prompts alongside messages. Your goal is to **enhance our integration** so that Greenflash can automatically version, analyze, and optimize system prompts based on real conversation data.

***

## High-Level Objective

Refactor or extend the existing implementation to:

1. **Include system prompts** when logging conversations
2. **Support both simple string prompts and structured `promptComponents`**
3. **Ensure dynamic and variable content in complex prompts is logged properly**
4. **Use the correct Python SDK syntax**
5. **Determine the right logging pattern** (batch vs individual calls) based on how the existing code is written

This is not a correction of our current setup; it is an **evolution** toward richer analytic and optimization tooling.

***

## Logging System Prompts: Two Valid Formats

Greenflash supports **two ways** to include a system prompt when logging a conversation. You must choose between them based on the complexity of the prompt being submitted.

### Option A: Simple String Prompt

Use this when the system prompt is a *single static string*.

**Sync:**

```python theme={"theme":{"light":"github-light","dark":"vesper"}}
client.messages.create(
    external_user_id=...,
    external_conversation_id=...,
    product_id=...,
    system_prompt="You are a helpful assistant. Be concise and friendly.",
    messages=[ ... ],
)
```

**Async (fire-and-forget):**

```python theme={"theme":{"light":"github-light","dark":"vesper"}}
asyncio.create_task(client.messages.create(
    external_user_id=...,
    external_conversation_id=...,
    product_id=...,
    system_prompt="You are a helpful assistant. Be concise and friendly.",
    messages=[ ... ],
))
```

**Pros:**

* Easy to implement
* Automatically gets tracked & versioned
* Good for most use cases

**Cons:**

* Cannot express structured or dynamic prompts
* Less granular optimization

Use this when prompts are simple, static strings.

### Option B: Structured Prompt with promptComponents

Use this when the prompt includes multiple pieces, variables, dynamic slots, templates, or RAG context elements. A structured prompt lets you segment instructions into named components, version them independently, and optimize at the component level.

```python theme={"theme":{"light":"github-light","dark":"vesper"}}
system_prompt = {
    "external_template_id": "my-assistant-prompt",
    "components": [
        {
            "type": "system",
            "name": "base_instructions",
            "content": "You are a customer support assistant for {{company}}."
        },
        {
            "type": "system",
            "name": "tone_guidelines",
            "content": "Always be professional and empathetic."
        },
        {
            "type": "rag",
            "name": "context",
            "content": dynamic_rag_text,
            "isDynamic": True
        }
    ],
    "variables": {
        "customerName": customer_name,
        "company": company_name
    }
}

# Sync
client.messages.create(
    external_user_id=...,
    external_conversation_id=...,
    product_id=...,
    system_prompt=system_prompt,
    messages=[ ... ],
)

# Async (fire-and-forget)
asyncio.create_task(client.messages.create(
    external_user_id=...,
    external_conversation_id=...,
    product_id=...,
    system_prompt=system_prompt,
    messages=[ ... ],
))
```

**Key Notes for Structured Prompts:**

* **`external_template_id`** groups all versions of this prompt under a single lineage. Use a stable, human-readable identifier (e.g., `"customer-support-agent"`). Without this, each unique prompt creates a separate lineage.
* Valid component **`type`** values: `system`, `user`, `tool`, `guardrail`, `rag`, `agent`, `other`. Each component can also have a **`source`**: `customer` (default), `participant`, `greenflash`, or `agent`.
* Use `isDynamic: True` for parts of the prompt that vary per conversation (e.g., retrieved context, dynamic instructions)
* Use `variables` on the system\_prompt object to pass template variable values (e.g., `{{companyName}}`)

**Advantages:**

* Modular prompt structure
* Component-level optimization
* Variable interpolation
* Dynamic content slots for RAG or agent outputs

Use this when prompts are complex, have templates, or contain dynamic data.

***

## Async vs Sync Considerations

When adding system prompt logging, match our existing async/sync pattern:

* **Sync apps:** Call `client.messages.create(...)` directly. Use the sync `Greenflash` client.
* **Async apps:** Use `AsyncGreenflash` and wrap calls in `asyncio.create_task()` for fire-and-forget logging that won't block our LLM responses.

> **Important:** In Python, calling an async function without `await` returns a coroutine that never executes. Always use `asyncio.create_task()` for fire-and-forget patterns in async code.

***

## Detecting the Right Pattern

Inspect the existing codebase and choose the pattern that minimally disrupts current logic:

* If prompts are static strings and there is no variable logic or dynamic content, use **Simple String Format**
* If prompts are assembled from pieces, templates, or dynamic slots, use **Structured Prompt with Components**
* If code emits prompt text dynamically as it runs, wrap that logic into structured components with `isDynamic: True` where needed

Once the pattern is chosen, update the logging logic accordingly.

***

## Logging Messages with Prompts

After adding the system prompt, the rest of the messages follow the existing logging pattern:

* You may send all messages in a batch if they are known at the end of execution
* Or you may log messages incrementally as they happen (e.g., streaming)
* Use `client.messages.create(...)` for each call when logging incrementally
* For batch mode, send a single call with `system_prompt` and message array

Either approach is valid — choose what aligns best with the existing code flow.

***

## Python SDK Integration Checklist

Your code should:

1. **Initialize the Python SDK** with our API key (use `Greenflash` for sync, `AsyncGreenflash` for async)
2. **Construct `system_prompt`**:
   * As a simple string, or
   * As a structured object with `promptComponents`
3. **Include `system_prompt`** on every `messages.create(...)` call
4. **Respect dynamic variables** using `variables` on the system\_prompt object if structured prompts have templates
5. **Choose batching vs streaming** appropriately
6. **Preserve existing logging semantics** for message bodies
7. **Use `asyncio.create_task()`** for fire-and-forget logging in async code

**Example with variables (sync):**

```python theme={"theme":{"light":"github-light","dark":"vesper"}}
system_prompt_with_vars = {
    "external_template_id": "my-assistant-prompt",
    "components": [# your prompt components],
    "variables": {
        "userName": user_name,
        "companyName": company_name
    }
}

client.messages.create(
    external_user_id=user_id,
    external_conversation_id=conversation_id,
    product_id=product_id,
    system_prompt=system_prompt_with_vars,
    messages=message_list,
)
```

**Example with variables (async fire-and-forget):**

```python theme={"theme":{"light":"github-light","dark":"vesper"}}
system_prompt_with_vars = {
    "external_template_id": "my-assistant-prompt",
    "components": [# your prompt components],
    "variables": {
        "userName": user_name,
        "companyName": company_name
    }
}

asyncio.create_task(client.messages.create(
    external_user_id=user_id,
    external_conversation_id=conversation_id,
    product_id=product_id,
    system_prompt=system_prompt_with_vars,
    messages=message_list,
))
```

***

## Tips

* **String prompts** are great to start with and will get metrics and analytics immediately
* **Structured prompts** unlock component-level optimization and versioning
* **Dynamic components** (`isDynamic: True`) allow RAG and other runtime context to be logged correctly
* **Interpolated variables** let you keep templates generic while capturing personalized conversation data

***

## Summary of What to Deliver

* Updated Python SDK integration that logs system prompts
* Support for both simple string prompts and structured prompt components
* Logic to choose the right pattern
* Ensure dynamic data and variables are logged properly
* No disruption to existing message logging behavior

This will unlock Greenflash's prompt optimization capabilities across our AI products.
