Greenflash Python SDK Integration Plan
Your task is to integrate the Greenflash Python SDK into this codebase and ship the minimal, correct implementation to start sending conversation data. Follow the steps below carefully and exactly, and make sure to use the checklist at the end to ensure you’ve followed all the steps. Important: Before implementing, analyze the codebase to understand:- Is it async or sync?
- Where does user input get received vs. where LLM responses are generated?
- Are they in the same function/location or separate?
0) Pre-flight checks (async vs sync, aiohttp)
-
Determine whether this codebase is async:
- Look for FastAPI/Starlette/aiohttp usage,
async defroute handlers, or an activeasyncioloop. - If none of the above, treat as sync.
- Look for FastAPI/Starlette/aiohttp usage,
-
Check if
aiohttpis already in use:- Search for
import aiohttpor anaiohttpdependency inpyproject.toml/requirements.txt.
- Search for
-
Install the correct SDK variant:
- Async app (and
aiohttpis present or acceptable to add): - Sync app (or you don’t want to add
aiohttp):
- Async app (and
Note: The--preflag is required because the Python SDK is currently in pre-release. Theaiohttpextra provides better performance in async environments. For sync apps, the base package is sufficient.
1) Configuration
-
Ensure the API key is available at runtime:
- Add to your environment (or
.envif the project uses python-dotenv): - Do not hard-code the key.
- The SDK will automatically read
GREENFLASH_API_KEYfrom environment variables if not passed explicitly.
- Add to your environment (or
-
Ensure you have your Product ID:
- Find your Product ID in Greenflash for the product you want to track.
- You will pass this directly to each API call (not as an env var), since a single codebase may serve multiple products.
2) Create a single reusable Greenflash client
Best practice: create one module that exports a ready-to-use client. Name it greenflash_client.py. Keep all env lookups centralized here.
For sync apps:
For async apps:
app/services/greenflash_client.py).
Import client wherever you log messages or identify users/orgs.
3) Log messages with client.messages.create (required fields only)
Required fields:
product_idexternal_user_idexternal_conversation_idmessages→ list of{ "role": "user" | "assistant" | "system", "content": str }
model— the AI model used (e.g.,"gpt-4o","claude-sonnet-4-20250514"). Enables model performance comparison in Greenflash.external_organization_id— links conversations to an organization/account for segment analysis.properties— dict of custom metadata to attach to the conversation.
3A) If the app is async, use AsyncGreenflash
UseAsyncGreenflash for native async support. Fire-and-forget with asyncio.create_task() to avoid blocking.
Note: If you’re using the syncGreenflashclient in an async app, wrap the call withasyncio.to_thread()instead:asyncio.create_task(asyncio.to_thread(client.messages.create, **params))
3B) If the app is sync, call directly
3C) Where to call it in your flow — choosing the right pattern
The Greenflash messages API is flexible: You can send 1 to many messages per call. Subsequent calls are automatically ordered by timestamp, so you can safely send:- Each message individually (user message, then assistant message separately)
- Messages grouped as turns (user + assistant together in one call)
- An entire conversation at once (less common for real-time logging)
-
Analyze your codebase structure first:
- Look for where user input is received and where the assistant/LLM response is generated
- Check if these happen in the same function or in different parts of the code
-
Pattern A - Send as turns:
- Use if: User input and assistant output are available together in the same function/location
- Example: Your LLM handler receives user input, generates a response, and returns both
- Benefit: One API call per turn, simpler tracking
-
Pattern B - Send individually:
- Use if: User input and assistant output are handled in separate functions/locations
- Example: User input handler is separate from the LLM response generation
- Benefit: Log as events happen, no need to refactor code structure
- Greenflash automatically orders messages by timestamp across calls, so both patterns work correctly
- Choose the pattern that requires minimal changes to the existing codebase
- You can mix patterns if needed (e.g., some conversations logged as turns, others as individual messages)
4) Minimal examples for message payload
5) (Optional) Agentic Workflows
If the product is an AI agent with tool calls, reasoning steps, or multi-step workflows, you can use structuredmessage_type values instead of simple role to give Greenflash richer visibility into agent behavior.
Key concepts:
- Use
message_typeinstead ofroleto describe what the agent is doing - Use
contentonly for user-facing input/output - Use
outputfor internal agent data (thoughts, tool results) - Use
inputfor tool call parameters - Link related messages with
external_message_idandparent_external_message_id
For more details: See the Agentic Messages prompt for comprehensive guidance on message types,contentvsoutput, and modeling complex agent execution.
6) (Optional) Identify users — only the required field
Call once when a user logs in or as soon as a stable ID is available. Required:external_user_id.
Optional fields you can include: external_organization_id, name, email, phone, properties (dict for custom data).
Async app (using AsyncGreenflash)
Sync app
7) (Optional) Identify organizations — only the required field
Use when you have a clear organization/account ID. Required:external_organization_id.
Optional fields you can include: name, properties (dict for custom data).
Async app (using AsyncGreenflash)
Sync app
8) Error handling (recommended for production)
While fire-and-forget logging is appropriate for most cases, you may want to handle errors for monitoring purposes:APIConnectionError, RateLimitError, APIStatusError, APITimeoutError, APIError (base class).
9) File/PR checklist
- Installed the correct package:
- Async + ok with aiohttp →
pip install --pre "greenflash[aiohttp]" - Otherwise →
pip install --pre greenflash
- Async + ok with aiohttp →
- Added
GREENFLASH_API_KEYto runtime env (not hard-coded). - Have your Product ID ready (from Greenflash) to pass directly in each API call.
- Created
greenflash_client.pywith the appropriate client:- Async apps →
AsyncGreenflash - Sync apps →
Greenflash
- Async apps →
- Analyzed codebase to determine message logging pattern:
- User input + assistant output in same location → use Pattern A (send as turns)
- User input + assistant output in separate locations → use Pattern B (send individually)
- Logging messages with only required fields:
product_id,external_user_id,external_conversation_id,messages. - Passing
product_iddirectly in eachclient.messages.create(...)call (not from an env var). - In async paths, used
asyncio.create_task(client.messages.create(...))for fire-and-forget logging (non-blocking). - (Optional) Added
client.users.create(...)where a stable user ID exists. - (Optional) Added
client.organizations.create(...)where an org ID exists.
greenflash_client.py, minimal logging wired into the main chat flow (using the appropriate pattern based on codebase structure), and optional user/org identification hooks. Include README notes describing env vars and where the logging occurs.
