Chat Agent¶
PydanticAI agent with 4 tools, streamed via AG-UI protocol.
Agent¶
agent
¶
PydanticAI attribution agent with domain tools.
Provides four domain tools for CopilotKit frontend interaction via the AG-UI (Agent-GUI) protocol. The agent acts as a conversational interface to the attribution scaffold, enabling artists, managers, and musicologists to query, review, and improve attribution records through natural language.
Tools
explain_confidence Explain why a work has a given confidence score by decomposing source agreement, corroborating sources, and assurance level. search_attributions Search across attribution records by title, artist, or keyword using the hybrid search service (text + vector + graph). suggest_correction Propose a correction to a specific field on an attribution record, generating a CorrectionPreview for frontend review. submit_feedback Submit a structured FeedbackCard for an attribution record, including overall assessment and optional free-text notes.
Notes
The agent uses PydanticAI's Agent class with dependency injection
(AgentDeps) for database access. The system prompt encodes domain
knowledge about A0-A3 assurance levels, the Oracle Problem, and
conformal prediction (see Teikari 2026, Sections 3-5).
The model identifier is loaded lazily from Settings.attribution_agent_model
so that import-time side effects are avoided and tests can mock the model.
See Also
music_attribution.chat.state : Shared agent/frontend state model. music_attribution.chat.agui_endpoint : AG-UI SSE streaming endpoint.
AgentDeps
dataclass
¶
AgentDeps(
state: AttributionAgentState,
session_factory: async_sessionmaker[AsyncSession]
| None = None,
)
Dependencies injected into PydanticAI agent tools at runtime.
PydanticAI's dependency injection system passes this object to every
tool call via ctx.deps. Tools use the session factory for
async database access and the state object for AG-UI state
synchronisation with the CopilotKit frontend.
| ATTRIBUTE | DESCRIPTION |
|---|---|
state |
Shared mutable state that is serialised as AG-UI StateSnapshot
events and consumed by CopilotKit
TYPE:
|
session_factory |
SQLAlchemy async session factory bound to the PostgreSQL engine.
TYPE:
|
ExplainConfidenceResult
¶
Bases: BaseModel
Structured result of the explain_confidence tool.
Captures both the numeric score and the human-readable explanation with contributing factors, enabling the frontend to render a rich confidence breakdown panel.
| ATTRIBUTE | DESCRIPTION |
|---|---|
work_id |
Attribution record identifier that was explained.
TYPE:
|
confidence_score |
Overall confidence score (0.0--1.0).
TYPE:
|
explanation |
Human-readable explanation combining all factors.
TYPE:
|
factors |
Individual contributing factors (source agreement, number of sources, assurance level) as separate strings.
TYPE:
|
SearchResult
¶
Bases: BaseModel
A single attribution search result returned by the agent.
Provides the minimal fields needed for the frontend to render a search result row: title, artist, confidence, and assurance.
| ATTRIBUTE | DESCRIPTION |
|---|---|
attribution_id |
UUID of the matching attribution record.
TYPE:
|
work_title |
Display title of the musical work.
TYPE:
|
artist_name |
Primary artist name.
TYPE:
|
confidence_score |
Overall confidence score (0.0--1.0).
TYPE:
|
assurance_level |
A0--A3 assurance level string (e.g.
TYPE:
|
SearchResultSet
¶
Bases: BaseModel
Aggregated result set from the search_attributions tool.
Wraps the query, matching results, and total count for pagination.
| ATTRIBUTE | DESCRIPTION |
|---|---|
query |
The original search query string.
TYPE:
|
results |
Matching attribution records (up to the limit).
TYPE:
|
total_count |
Total number of matches (may exceed
TYPE:
|
SuggestCorrectionResult
¶
Bases: BaseModel
Result of the suggest_correction tool.
Pairs the target work with a CorrectionPreview that the frontend
renders as a diff (current value vs. suggested value) for user
approval before submission.
| ATTRIBUTE | DESCRIPTION |
|---|---|
work_id |
Attribution record identifier to correct.
TYPE:
|
correction |
Structured preview of the proposed change.
TYPE:
|
SubmitFeedbackResult
¶
Bases: BaseModel
Result of the submit_feedback tool.
Returned after a FeedbackCard is persisted, confirming the submission and indicating whether center-bias was detected.
| ATTRIBUTE | DESCRIPTION |
|---|---|
feedback_id |
UUID of the created FeedbackCard.
TYPE:
|
attribution_id |
UUID of the attribution record the feedback targets.
TYPE:
|
accepted |
Whether the feedback was successfully stored.
TYPE:
|
message |
Human-readable confirmation message (may include bias warning).
TYPE:
|
create_attribution_agent
¶
create_attribution_agent() -> Agent[AgentDeps, str]
Create and configure the PydanticAI attribution agent.
Instantiates a PydanticAI Agent with a domain-specific system
prompt and registers four tool functions (explain_confidence,
search_attributions, suggest_correction, submit_feedback).
The agent model identifier is resolved lazily from application
settings via _get_agent_model(). The agent is configured with
retries=2 for transient LLM failures.
| RETURNS | DESCRIPTION |
|---|---|
Agent[AgentDeps, str]
|
Configured PydanticAI Agent with four domain tools, typed to
accept |
Notes
Tool functions are registered using PydanticAI's @agent.tool
decorator, which provides automatic parameter validation and
dependency injection via ctx.deps.
Each tool updates ctx.deps.state to synchronise AG-UI state
with the CopilotKit frontend (e.g. setting current_work_id
after explaining a confidence score).
Source code in src/music_attribution/chat/agent.py
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | |
Chat State¶
state
¶
Shared state model for the attribution chat agent.
Defines the Pydantic models that represent the mutable conversation state
shared between the PydanticAI agent (backend) and CopilotKit (frontend)
via the AG-UI protocol. State changes are serialised as StateSnapshot
and StateDelta Server-Sent Events.
The frontend observes this state through CopilotKit's
useCopilotReadable hooks, enabling real-time UI updates when the
agent sets current_work_id, confidence_score, or
pending_correction.
| CLASS | DESCRIPTION |
|---|---|
AttributionAgentState |
Main state container with fields for the current work context, search state, and pending corrections. |
CorrectionPreview |
Preview of a proposed field correction awaiting user approval. |
See Also
music_attribution.chat.agent : Agent that mutates this state. music_attribution.chat.agui_endpoint : SSE endpoint that serialises this state.
AttributionAgentState
¶
Bases: BaseModel
Shared state between the PydanticAI agent and CopilotKit frontend.
Every field in this model is serialised as an AG-UI StateSnapshot
event after each agent turn. CopilotKit useCopilotReadable hooks
on the frontend subscribe to individual fields for reactive UI
updates (e.g. highlighting the current work, showing search counts).
Agent tools mutate this state via ctx.deps.state during
execution. The AG-UI endpoint serialises the final state at the
end of each run.
| ATTRIBUTE | DESCRIPTION |
|---|---|
current_work_id |
Attribution ID of the work currently being discussed. Set by
TYPE:
|
current_work_title |
Display title of the current work for the frontend header.
TYPE:
|
confidence_score |
Confidence score (0.0--1.0) currently under discussion. Constrained to [0.0, 1.0] via Pydantic validators.
TYPE:
|
review_queue_size |
Number of works pending human review. Non-negative.
TYPE:
|
pending_correction |
Preview of a correction the agent is suggesting. The frontend renders this as a before/after diff. Cleared after feedback submission.
TYPE:
|
explanation_text |
Agent's current natural-language explanation of a confidence score, displayed in the chat sidebar.
TYPE:
|
last_search_query |
Most recent search query executed by the agent.
TYPE:
|
last_search_count |
Number of results from the most recent search. Non-negative.
TYPE:
|
CorrectionPreview
¶
Bases: BaseModel
Preview of a proposed field correction before user approval.
Generated by the suggest_correction agent tool and stored in
AttributionAgentState.pending_correction. The CopilotKit
frontend renders this as a diff view (current vs. suggested value)
with the agent's reasoning and confidence level.
| ATTRIBUTE | DESCRIPTION |
|---|---|
field |
Name of the attribution record field being corrected
(e.g.
TYPE:
|
current_value |
Current value of the field in the attribution record.
TYPE:
|
suggested_value |
Proposed replacement value.
TYPE:
|
reason |
Agent's justification for the correction, displayed to the reviewer for informed approval/rejection.
TYPE:
|
confidence_in_correction |
Agent's confidence in the suggested correction (0.0--1.0). Constrained to [0.0, 1.0] via Pydantic validators.
TYPE:
|
AG-UI Endpoint¶
agui_endpoint
¶
AG-UI protocol endpoint for CopilotKit integration.
Implements a simplified AG-UI (Agent-GUI) protocol adapter that streams Server-Sent Events (SSE) from the PydanticAI attribution agent to the CopilotKit frontend. The AG-UI protocol defines 31 event types; this adapter implements the subset needed for text-based conversation:
RunStarted/RunFinished-- lifecycle bookendsTextMessageStart/TextMessageContent/TextMessageEnd-- streamed assistant responseStateSnapshot-- full agent state for frontend synchronisation
In production, PydanticAI's AGUIAdapter would replace this
simplified implementation to support the full event catalogue
(tool calls, state deltas, action requests, etc.).
The endpoint is mounted at /api/v1/copilotkit and accepts POST
requests with the CopilotKit message payload.
Notes
The agent instance is a lazy singleton (_get_agent) to avoid
requiring an Anthropic API key at import time. Tests mock this
function to inject a test agent.
See Also
music_attribution.chat.agent : Agent factory and tool definitions. music_attribution.chat.state : Shared state model.
copilotkit_endpoint
async
¶
CopilotKit AG-UI endpoint for agent conversation.
Receives a CopilotKit message payload via POST, extracts the conversation history, and returns an SSE stream of AG-UI events generated by the PydanticAI attribution agent.
The endpoint extracts the async_session_factory from
request.app.state (set during FastAPI startup) to give agent
tools database access.
SSE response headers disable caching and buffering to ensure low-latency event delivery to the frontend.
| PARAMETER | DESCRIPTION |
|---|---|
request
|
FastAPI request containing a JSON body with
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
StreamingResponse
|
SSE stream ( |