Files
zeekay 159e825022 merge: take upstream master fa1a9a60 onto the converged tree
The five days of upstream evolution since the 2026-08-01 import land through
bin/debrand: new query schema, billing counters, ducklake compaction, the
desktop sandbox default, capture evolution. Ours' invariants hold everywhere
they met it: IAM-native auth only, no ee, no upsell surfaces, one sessions
model, org-is-the-tenant, v1-first serving, fail-closed capture. Crates and
workflows the fork retired stay retired; the Lemon prefix finishes dissolving
into elements.
2026-08-06 05:33:45 -07:00

181 lines
7.6 KiB
TypeScript

import { OnboardingComponentsContext, createInstallation } from 'scenes/onboarding/shared/OnboardingDocsContentWrapper'
import { StepDefinition } from '../steps'
export const getCrewAISteps = (ctx: OnboardingComponentsContext): StepDefinition[] => {
const { CodeBlock, CalloutBox, Markdown, dedent, snippets } = ctx
const NotableGenerationProperties = snippets?.NotableGenerationProperties
return [
{
title: 'Install the Insights SDK',
badge: 'required',
content: (
<>
<Markdown>
Setting up analytics starts with installing the Insights SDK. CrewAI uses LiteLLM under the hood,
and Insights integrates with LiteLLM's callback system.
</Markdown>
<CodeBlock
language="bash"
code={dedent`
pip install insights
`}
/>
</>
),
},
{
title: 'Install CrewAI',
badge: 'required',
content: (
<>
<Markdown>
Install CrewAI. Insights instruments your LLM calls through LiteLLM's callback system that CrewAI
uses natively.
</Markdown>
<CodeBlock
language="bash"
code={dedent`
pip install crewai litellm
`}
/>
</>
),
},
{
title: 'Configure Insights with LiteLLM',
badge: 'required',
content: (
<>
<Markdown>
Set your Insights project token and host as environment variables, then configure LiteLLM to use
Insights as a callback handler. You can find your project token in [your project
settings](https://app.hanzo.ai/settings/project).
</Markdown>
<CodeBlock
language="python"
code={dedent`
import os
import litellm
from crewai import Agent, Task, Crew, LLM
# Set Insights environment variables
os.environ["INSIGHTS_API_KEY"] = "<ph_project_token>"
os.environ["INSIGHTS_API_URL"] = "<ph_client_api_host>"
# Enable Insights callbacks in LiteLLM
litellm.success_callback = ["insights"]
litellm.failure_callback = ["insights"]
`}
/>
<CalloutBox type="fyi" icon="IconInfo" title="How this works">
<Markdown>
CrewAI can route LLM calls either through its own provider clients or through LiteLLM.
Insights hooks into LiteLLM's callback system, so you need `is_litellm=True` on the `LLM` you
pass to your agents. With it, Insights captures every call as an `$ai_generation` event,
without proxying your calls.
</Markdown>
</CalloutBox>
</>
),
},
{
title: 'Run your crew',
badge: 'required',
content: (
<>
<Markdown>
{dedent`
Run your CrewAI agents as normal. Insights automatically captures an \`$ai_generation\`
event for each LLM call. LiteLLM's callback does not see the tools your agents call.
Capture a tool's own execution as a span from inside the tool itself instead, as
\`my_tool\` does below.
`}
</Markdown>
<CodeBlock
language="python"
code={dedent`
from insights import Insights
from crewai.tools import tool
import time, uuid
insights = Insights("<ph_project_token>", host="<ph_client_api_host>")
trace_id = str(uuid.uuid4())
@tool
def my_tool(query: str) -> str:
"""Describe what your tool does."""
start = time.time()
result = run_tool(query)
insights.capture(
distinct_id="user_123",
event="$ai_span",
properties={
"$ai_trace_id": trace_id,
"$ai_session_id": "conversation-abc",
"$ai_span_id": str(uuid.uuid4()),
"$ai_span_name": "my_tool",
"$ai_input_state": {"query": query},
"$ai_output_state": result,
"$ai_latency": time.time() - start,
},
)
return result
# is_litellm=True routes calls through LiteLLM so the Insights
# callback fires. Without it, CrewAI uses its own provider client
# and no events are captured.
llm = LLM(
model="gpt-4o-mini",
is_litellm=True,
metadata={
"user_id": "user_123",
"$ai_session_id": "conversation-abc",
"$ai_trace_id": trace_id,
},
)
researcher = Agent(
role="Researcher",
goal="Find the weather in a city",
backstory="You are an expert wildlife researcher.",
llm=llm,
tools=[my_tool],
)
task = Task(
description="Find the weather in Paris.",
expected_output="The weather in Paris.",
agent=researcher,
)
crew = Crew(agents=[researcher], tasks=[task])
result = crew.kickoff()
print(result)
`}
/>
<Markdown>
{dedent`
You can expect captured \`$ai_generation\` events to have the following properties:
`}
</Markdown>
{NotableGenerationProperties && <NotableGenerationProperties />}
</>
),
},
]
}
export const CrewAIInstallation = createInstallation(getCrewAISteps)