Managed Prompt
Managed Prompt
ManagedPrompt은 에이전트의 지시문을 Logfire-managed prompt로 뒷받침해요. 코드를 건드리거나 재배포하지 않고 Logfire UI에서 시스템 프롬프트를 반복·버전화·라벨·롤아웃할 수 있게 해 주죠. Pydantic AI capability라서 Agent의 capabilities= 파라미터로 끼워 넣어요.
logfire 엑스트라를 설치하세요:
pip install "pydantic-ai-harness[logfire]"
uv add "pydantic-ai-harness[logfire]"
1차 Managed capability가 진행 중이에요
더 넓은 1차 Managed capability가 pydantic-ai#5107에서 개발 중이고, 결국 pydantic_ai.managed.logfire.Managed로 임포트 가능해질 거예요 — 지시문·모델 설정·전체 스펙 변수를 다루죠. 그때까지는 ManagedPrompt이 에이전트의 지시문을 Logfire-managed prompt로 뒷받침하는 지원 경로예요.
Pydantic AI Harness가 0.x 릴리스인 동안 API는 마이너 릴리스 사이에 바뀔 수 있어요. 바뀔 때는 폐기 경고와 릴리스 노트 마이그레이션 안내가 정확히 어떻게 업그레이드할지 알려줘요. 버전 정책 참고.
출처: 문서
본문
그것이 해결하는 문제 (The problem it solves)
프롬프트는 에이전트 동작에 결정적이지만, 평범한 편집 -> 리뷰 -> 배포 루프로 반복하는 것은 느려요. 변경을 A/B 테스트하기 쉽지 않고, 프로덕션에서 즉시 잘못 행동할 때 새 빌드를 배포하지 않고 롤백하기 어려워요.
ManagedPrompt은 프롬프트를 코드베이스 밖, Logfire의 관리형 변수 저장소로 옮겨요. 백킹 관리형 변수를 선언하고 실행당 한 번 해석해, 해석된 값을 에이전트 지시문에 넣어요. 해석은 실행의 wrap_run 훅 안에서 일어나고, ResolvedVariable을 전체 실행 동안 열려 있는 컨텍스트 매니저로 사용해요. 그래서 선택된 라벨과 버전이 에이전트 실행의 모든 자식 스팬에 baggage로 붙어요. 실행의 동작과 그것을 만든 정확한 프롬프트 버전 사이의 직접 상관관계와, Logfire UI에서의 즉시 반복·롤백을 얻어요.
사용법 (Usage)
프롬프트 이름과 기본값을 넘기세요. support_agent 이름은 prompt__support_agent라는 관리형 변수로 선언돼요. Logfire의 Prompt 관리가 쓰는 명명이죠(이름의 하이픈은 밑줄이 됨). default는 원격 값이 게시될 때까지 에이전트가 동작하게 유지해서, Logfire에서 프롬프트를 만들기 전에도 코드가 항상 실행돼요.
import logfire
from pydantic_ai import Agent
from pydantic_ai_harness import ManagedPrompt
logfire.configure()
agent = Agent(
'openai:gpt-5',
capabilities=[
ManagedPrompt(
'support_agent',
default='You are a helpful customer support agent. Be friendly and concise.',
label='production',
)
],
)
result = agent.run_sync('My order never arrived.')
print(result.output)
label='production'을 고정하는 것이 권장 기본값이에요. 해석된 값이 의도적인 프롬프트 롤아웃에서만 바뀌므로, 프로바이더 프롬프트 캐시를 뜨겁게 유지해요 (Prompt-cache trade-off 참고).
타게팅 (Targeting)
결정적 A/B 할당(같은 사용자는 항상 같은 라벨을 봄)을 위해 targeting_key를 넘기세요. 정적 문자열이거나, RunContext에서 키를 파생하는 호출 가능일 수 있어요. 키가 에이전트의 deps에 있을 때 유용하죠:
from dataclasses import dataclass
from pydantic_ai import Agent
from pydantic_ai_harness import ManagedPrompt
@dataclass
class Deps:
user_id: str
agent = Agent(
'openai:gpt-5',
deps_type=Deps,
capabilities=[
ManagedPrompt(
'support_agent',
default='You are a helpful customer support agent.',
targeting_key=lambda ctx: ctx.deps.user_id,
),
],
)
조건 기반 타게팅 규칙에는 attributes(매핑, 또는 하나를 반환하는 호출 가능)를 넘기세요. label이 생략되면 변수의 롤아웃과 타게팅 규칙이 라벨을 골라요. targeting_key와 attributes가 모두 생략되면 Logfire는 자체 타게팅 컨텍스트로, 그다음 활성 trace id로 폴백해요.
에이전트 밖에 사는 Logfire 측 타게팅(예: 요청 핸들러당 한 번 설정)에는 바깥 범위에서 Logfire의 targeting_context를 사용하세요. ManagedPrompt은 키가 에이전트의 RunContext에서 올 때만 targeting_key / attributes가 필요해요.
deps로 템플릿 (Templating with deps)
기본적으로 해석된 프롬프트는 그대로 사용돼요. render_template=True를 넘기면 TemplateStr와 같은 메커니즘으로, 에이전트의 deps에 대해 Handlebars 템플릿으로 렌더링해요. {{field}}가 deps에서 채워지죠:
from dataclasses import dataclass
from pydantic_ai import Agent
from pydantic_ai_harness import ManagedPrompt
@dataclass
class Deps:
customer_name: str
agent = Agent(
'openai:gpt-5',
deps_type=Deps,
capabilities=[
ManagedPrompt(
'support_agent',
default='You are helping {{customer_name}}. Be friendly and concise.',
render_template=True,
),
],
)
렌더링에는 pydantic-handlebars(pydantic-ai-slim[spec] 설치)가 필요해요. 기본적으로 꺼져 있어요.
프롬프트-캐시 트레이드오프 (Prompt-cache trade-off)
해석된 값은 에이전트의 시스템 지시문에 들어가요. 프로바이더 프롬프트 캐시(Anthropic, OpenAI 등)는 프리픽스로 엄격히 키잉돼요. tools -> system -> messages. 그래서 시스템 블록의 어떤 변경이든 영향을 받는 실행의 캐시된 프리픽스를 무효화해요.
| 모드 | 캐시 영향 |
|---|---|
고정 label='production', 롤아웃 분할 없음 |
캐시 안정. 값은 의도적인 프롬프트 롤아웃에서만 바뀌는데, 이는 재배포와 같은 비용 |
라벨 건너 퍼센트 롤아웃 (label= 없음) |
다른 실행이 다른 라벨에 떨어짐 -> 캐시를 라벨당 차선 하나로 분할 |
여러 라벨이 있는 사용자/테넌트별 targeting_key |
할당된 라벨당 캐시 차선; 키당 결정적이지만 전체적으로 여전히 N 차선 |
| Logfire UI에서 트래픽 중 라벨 플립 | 그 라벨의 모든 사람에게 일회성 콜드 무효화 |
요컨대: label을 고정하면 캐시가 뜨겁게 유지되고, ManagedPrompt을 A/B 플랫폼으로 쓰는 것은 선택적 캐시 비용이에요. 롤아웃이 필요 없으면 label='production'이 권장 기본값이에요.
자신의 변수 가져오기 (Bringing your own variable)
같은 이름을 두 번 이상 선언해도 돼요. 각 ManagedPrompt이 자체 백킹 변수를 만들므로 프롬프트를 여러 에이전트에 걸쳐 공유하는 게 그냥 동작해요. 템플릿 변수나 variables_push로 등록된 것 같은, 변수를 직접 선언하고 싶으면 첫 인자에 이름 대신 기존 logfire.variables.Variable을 넘기세요:
import logfire
from pydantic_ai import Agent
from pydantic_ai_harness import ManagedPrompt
logfire.configure()
support_prompt = logfire.var(
name='prompt__support_agent',
type=str,
default='You are a helpful customer support agent. Be friendly and concise.',
)
agent = Agent('openai:gpt-5', capabilities=[ManagedPrompt(support_prompt, label='production')])
name이 프롬프트 이름(Variable 아님)일 때, logfire_instance=를 넘기면 모듈 수준 기본값 대신 특정 Logfire 인스턴스에 변수를 선언해요. default는 name이 프롬프트 이름일 때 필요하고, Variable(자체 기본값·인스턴스를 이미 담음)을 넘기면 무시돼요.
어떻게 구성되나 (How it composes)
- 실행당 한 번 해석. 실행 중 Logfire에 도착한 라벨 플립이나 롤아웃 변경은 다음 실행이 시작될 때까지 반영되지 않아요. 실행-안정적 지시문과 모든 자식 스팬에 걸친 단일 baggage 범위의 트레이드오프예요.
- 바깥에서 실행. capability가
Instrumentation을 감싸서, 해석된 변수의 baggage가 에이전트 실행 스팬과 자식 모두를 덮어요. 최근 Logfire 버전에서는 선택된 라벨과 버전이 별도 baggage 속성으로 전파돼요. - 동시성 안전. 해석은 컨텍스트 변수로 실행별 격리되어, 단일 capability 인스턴스를 동시 실행에 걸쳐 공유해도 안전해요.
- 실행 중 검사 가능.
ManagedPrompt.resolved는 활성 실행의ResolvedVariable(value,label,version,reason)를 검사하도록 노출해요 — 예를 들어 도구 안에서. 실행 밖에서는None이에요.
API 참고 (API reference)
해석된 프롬프트는 str이에요. 베어 프롬프트 이름(prompt__ 프리픽스와 하이픈-밑줄 정규화는 자동 적용)과 default를 넘긴 뒤, label, targeting_key, attributes, render_template, logfire_instance로 해석을 제어하세요.
ManagedPrompt
Bases: AbstractCapability[AgentDepsT]
에이전트의 지시문을 Logfire-managed prompt로 뒷받침.
Prompt-cache trade-off: 해석된 값이 시스템 지시문 블록에 들어가므로, 프롬프트에 대한 Logfire 측 변경(새 버전 롤아웃, 라벨 플립, A/B 타게팅)은 영향을 받는 실행의 프로바이더 프롬프트 캐시를 무효화해요. 캐시-안정 경로를 위해 label(예: 'production')을 고정하고, 퍼센트 롤아웃과 사용자별 타게팅은 선택적 캐시 비용으로 취급하세요. 전체 그림은 README의 "Prompt-cache trade-off" 섹션 참고.
관리형 프롬프트 이름과 기본값을 넘기면 capability가 당신을 위해 백킹 관리형 변수를 선언해요. support_agent 이름은 Logfire의 Prompt 관리가 쓰는 명명과 일치하게 prompt__support_agent 변수를 해석해요. 재배포 없이 Logfire UI에서 프롬프트를 반복·버전화·라벨·롤아웃할 수 있고, 원격 값이 없을 때 코드 기본값이 에이전트를 동작하게 유지해요.
import logfire
from pydantic_ai import Agent
from pydantic_ai_harness.logfire import ManagedPrompt
logfire.configure()
agent = Agent(
'openai:gpt-5',
capabilities=[
ManagedPrompt(
'support_agent',
default='You are a helpful customer support agent. Be friendly and concise.',
label='production',
)
],
)
result = agent.run_sync('My order never arrived.')
프롬프트 값은 실행의 wrap_run 훅 안에서 실행당 한 번 해석되고, ResolvedVariable을 전체 실행 동안 열려 있는 컨텍스트 매니저로 사용해요. 선택된 라벨과 버전이 에이전트 실행의 모든 자식 스팬에 baggage로 붙어요.
같은 이름을 두 번 이상 선언해도 돼요. 각 ManagedPrompt이 자체 백킹 변수를 만들므로 여러 에이전트에 걸친 프롬프트 공유가 그냥 동작해요. name에 프롬프트 이름 대신 기존 logfire.variables.Variable을 넘기면 직접 정의한 변수(예: template_var, 또는 variables_push에 등록된 것)를 쓸 수 있어요.
속성 (Attributes)
name
관리형 프롬프트 이름(prompt__<name> 변수로 선언됨) 또는 미리 만들어진 logfire.Variable.
default
코드 기본 프롬프트 텍스트. name이 프롬프트 이름일 때 필요; name이 Variable일 때 무시.
label
해석할 Logfire 관리형 프롬프트의 명시적 타게팅 라벨(예: 'production'). None이면 관리형 변수의 타게팅 규칙이 라벨을 선택.
targeting_key
Logfire의 결정적 롤아웃 할당을 시드하는 안정 키. 같은 키는 항상 같은 퍼센트 버킷에 떨어지므로, 주어진 사용자가 실행 전반에 걸쳐 같은 라벨을 유지해요. 정적 값 또는 RunContext에서 파생하는 호출 가능을 받음. None이면 Logfire가 자체 타게팅 컨텍스트로, 그다음 활성 trace id로 폴백.
타입: str | Callable[[RunContext[AgentDepsT]], str | None] | None 기본: None
attributes
조건 기반 타게팅 규칙용 속성, 또는 RunContext에서 파생하는 호출 가능.
타입: Mapping[str, Any] | Callable[[RunContext[AgentDepsT]], Mapping[str, Any] | None] | None 기본: None
render_template
True일 때 해석된 프롬프트를 에이전트의 deps에 대해 Handlebars 템플릿으로 렌더링(TemplateStr과 같은 메커니즘); {{field}}가 deps에서 채워짐. pydantic-handlebars(pydantic-ai-slim[spec] 설치) 필요. 기본 False라 해석된 프롬프트는 그대로 사용.
타입: bool 기본: False
logfire_instance
변수를 해석할 Logfire 인스턴스. None이면 전역 기본 인스턴스(모듈 수준 logfire.var을 뒷받침하는 것) 사용. name이 Variable일 때 무시.
타입: Logfire | None 기본: None
resolved
활성 실행의 프롬프트 해석, 또는 실행 밖에서 None.
전체 ResolvedVariable(value, label, version, reason, ...)을 노출해 어떤 프롬프트 버전이 작용 중인지 검사할 수 있게 해요.
타입: ResolvedVariable[str] | None
메서드 (Methods)
get_ordering
def get_ordering() -> CapabilityOrdering
프롬프트의 baggage가 실행 스팬을 포함해 전체 실행을 감싸도록 바깥에서 실행.
반환
CapabilityOrdering
get_instructions
def get_instructions() -> Callable[[RunContext[AgentDepsT]], str | None]
해석된 프롬프트를 에이전트의 시스템 프롬프트에 제공.
반환
Callable[[RunContext[AgentDepsT]], str | None]
wrap_run
@async
def wrap_run(
ctx: RunContext[AgentDepsT],
*,
handler: WrapRunHandler,
) -> AgentRunResult[Any]
프롬프트를 한 번 해석하고 그 baggage를 실행 기간 동안 활성으로 유지.
반환
더 알아보기 (Learn more)
- Logfire managed variables — 관리형 변수 시스템.
- Logfire prompt management — 프롬프트 관리.
- Pydantic AI Harness — 패키지 전반.