pyagentic-core 2.1.0a2__tar.gz → 2.1.0a3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/PKG-INFO +1 -1
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_agent/_agent.py +92 -58
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic_core.egg-info/PKG-INFO +1 -1
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyproject.toml +1 -1
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/LICENSE +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/README.md +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/__init__.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/__init__.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_agent/__init__.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_agent/_agent_linking.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_agent/_agent_state.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_exceptions.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_info.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_metaclasses.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_ref.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_spec.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_state.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_tool.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_base/_validation.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_utils/_typing.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/_utils/_warnings.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/llm/__init__.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/llm/_anthropic.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/llm/_gemini.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/llm/_mock.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/llm/_openai.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/llm/_openaiv1.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/llm/_provider.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/logging.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/models/llm.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/models/response.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/models/tracing.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/policies/__init__.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/policies/_events.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/policies/_policy.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/tracing/__init__.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/tracing/_basic.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/tracing/_langfuse.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/tracing/_tracer.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic/updates.py +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic_core.egg-info/SOURCES.txt +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic_core.egg-info/dependency_links.txt +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic_core.egg-info/requires.txt +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic_core.egg-info/top_level.txt +0 -0
- {pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/setup.cfg +0 -0
|
@@ -126,8 +126,6 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
126
126
|
api_key (str, optional): API key matching the model provider
|
|
127
127
|
provider (LLMProvider, optional): Pre-configured provider instance. Overrides
|
|
128
128
|
`model` and `api_key` if provided.
|
|
129
|
-
emitter (Callable, optional): Callback function to receive real-time updates
|
|
130
|
-
about the agent's execution (useful for WebSocket streaming)
|
|
131
129
|
tracer (AgentTracer, optional): Tracer instance for observability. Defaults
|
|
132
130
|
to BasicTracer if not provided.
|
|
133
131
|
max_call_depth (int): Maximum number of tool calling loops per run. Defaults to 1.
|
|
@@ -177,7 +175,6 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
177
175
|
model: str = None
|
|
178
176
|
api_key: str = None
|
|
179
177
|
provider: LLMProvider = None
|
|
180
|
-
emitter: Callable[[Any], str] = None
|
|
181
178
|
tracer: AgentTracer = None
|
|
182
179
|
max_call_depth: int = 1
|
|
183
180
|
|
|
@@ -314,8 +311,6 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
314
311
|
except Exception as e:
|
|
315
312
|
# Handle inference errors gracefully
|
|
316
313
|
logger.exception(e)
|
|
317
|
-
if self.emitter:
|
|
318
|
-
await _safe_run(self.emitter, EmitUpdate(status=Status.ERROR))
|
|
319
314
|
# Add error message to conversation history
|
|
320
315
|
self.state._messages.append(
|
|
321
316
|
Message(role="assistant", content="Failed to generate a response")
|
|
@@ -402,37 +397,15 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
402
397
|
# Handle validation errors for tool arguments
|
|
403
398
|
result = f"Function Args were invalid: {str(e)}"
|
|
404
399
|
compiled_args = {}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
logger.exception(e)
|
|
408
|
-
if self.emitter:
|
|
409
|
-
await _safe_run(
|
|
410
|
-
self.emitter,
|
|
411
|
-
ToolUpdate(
|
|
412
|
-
status=Status.ERROR, tool_call=tool_call.name, tool_args=kwargs
|
|
413
|
-
),
|
|
414
|
-
)
|
|
415
|
-
|
|
416
|
-
# Execute the tool, emitting status updates
|
|
400
|
+
self.tracer.record_exception(str(e))
|
|
401
|
+
logger.exception(e)
|
|
417
402
|
try:
|
|
418
|
-
if self.emitter:
|
|
419
|
-
await _safe_run(
|
|
420
|
-
self.emitter,
|
|
421
|
-
ToolUpdate(
|
|
422
|
-
status=Status.PROCESSING, tool_call=tool_call.name, tool_args=kwargs
|
|
423
|
-
),
|
|
424
|
-
)
|
|
425
403
|
if compiled_args:
|
|
426
404
|
result = await _safe_run(handler, **compiled_args)
|
|
427
405
|
self.tracer.set_attributes(result=result)
|
|
428
406
|
except TypeError as e:
|
|
429
407
|
self.tracer.record_exception(str(e))
|
|
430
408
|
logger.exception(e)
|
|
431
|
-
if self.emitter:
|
|
432
|
-
await _safe_run(
|
|
433
|
-
self.emitter,
|
|
434
|
-
ToolUpdate(status=Status.ERROR, tool_call=tool_call.name, tool_args=kwargs),
|
|
435
|
-
)
|
|
436
409
|
raise InvalidToolDefinition(
|
|
437
410
|
tool_name=tool_call.name,
|
|
438
411
|
message=f"Tool must have a serializable return type; {tool_def.return_type} failed to be casted to a string.",
|
|
@@ -442,11 +415,6 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
442
415
|
self.tracer.record_exception(str(e))
|
|
443
416
|
logger.exception(e)
|
|
444
417
|
result = f"Tool `{tool_call.name}` failed: {e}. Please kindly state to the user that is failed, provide state, and ask if they want to try again." # noqa E501
|
|
445
|
-
if self.emitter:
|
|
446
|
-
await _safe_run(
|
|
447
|
-
self.emitter,
|
|
448
|
-
ToolUpdate(status=Status.ERROR, tool_call=tool_call.name, tool_args=kwargs),
|
|
449
|
-
)
|
|
450
418
|
|
|
451
419
|
stringified_result = (
|
|
452
420
|
result.model_dump_json(indent=2)
|
|
@@ -492,10 +460,12 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
492
460
|
self, input_: str
|
|
493
461
|
) -> AsyncGenerator[Union[ToolResponse, AgentResponse, LLMResponse]]:
|
|
494
462
|
"""
|
|
495
|
-
|
|
496
|
-
|
|
463
|
+
Streams all intermediate responses as the agent executes. Yields LLMResponse for each
|
|
464
|
+
inference, ToolResponse for each tool execution, and finally AgentResponse with the
|
|
465
|
+
complete result.
|
|
497
466
|
|
|
498
|
-
|
|
467
|
+
This is the core execution method that enables real-time streaming and fine-grained
|
|
468
|
+
control over agent execution. The agent follows an agentic loop pattern:
|
|
499
469
|
1. Send user input and conversation history to the LLM
|
|
500
470
|
2. LLM decides to either call tools or respond with final output
|
|
501
471
|
3. If tools are called, execute them and feed results back to LLM
|
|
@@ -504,19 +474,23 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
504
474
|
Args:
|
|
505
475
|
input_ (str): The user input/query for the agent to process
|
|
506
476
|
|
|
507
|
-
|
|
508
|
-
AgentResponse:
|
|
509
|
-
-
|
|
510
|
-
-
|
|
511
|
-
-
|
|
512
|
-
- provider_info: Information about the LLM provider used
|
|
477
|
+
Yields:
|
|
478
|
+
Union[LLMResponse, ToolResponse, AgentResponse]: Responses in sequence:
|
|
479
|
+
- LLMResponse: Yielded each time the LLM is called (may happen multiple times)
|
|
480
|
+
- ToolResponse: Yielded for each tool execution
|
|
481
|
+
- AgentResponse: Final response with complete execution summary
|
|
513
482
|
|
|
514
483
|
Example:
|
|
515
484
|
```python
|
|
516
485
|
agent = MyAgent(model="openai::gpt-4o", api_key=API_KEY)
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
486
|
+
|
|
487
|
+
async for response in agent.step("Analyze this data"):
|
|
488
|
+
if isinstance(response, LLMResponse):
|
|
489
|
+
print(f"LLM thinking: {response.text}")
|
|
490
|
+
elif isinstance(response, ToolResponse):
|
|
491
|
+
print(f"Tool executed: {response.output}")
|
|
492
|
+
elif isinstance(response, AgentResponse):
|
|
493
|
+
print(f"Final: {response.final_output}")
|
|
520
494
|
```
|
|
521
495
|
"""
|
|
522
496
|
async with self.tracer.agent(
|
|
@@ -538,10 +512,6 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
538
512
|
agent_responses: list = []
|
|
539
513
|
processed_call_ids: set[str] = set()
|
|
540
514
|
|
|
541
|
-
# Emit initial status
|
|
542
|
-
if self.emitter:
|
|
543
|
-
await _safe_run(self.emitter, EmitUpdate(status=Status.GENERATING))
|
|
544
|
-
|
|
545
515
|
# Main agentic loop: LLM -> Tools -> LLM -> ...
|
|
546
516
|
depth = 0
|
|
547
517
|
final_ai_output: str | None = None
|
|
@@ -584,12 +554,6 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
584
554
|
response = await self._process_llm_inference()
|
|
585
555
|
final_ai_output = response.parsed if response.parsed else response.text
|
|
586
556
|
|
|
587
|
-
# Emit final success status
|
|
588
|
-
if self.emitter:
|
|
589
|
-
await _safe_run(
|
|
590
|
-
self.emitter, AiUpdate(status=Status.SUCCEDED, message=final_ai_output)
|
|
591
|
-
)
|
|
592
|
-
|
|
593
557
|
# Build the structured response
|
|
594
558
|
response_fields = {
|
|
595
559
|
"final_output": final_ai_output,
|
|
@@ -607,6 +571,32 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
607
571
|
yield response
|
|
608
572
|
|
|
609
573
|
async def run(self, input_: str) -> AgentResponse:
|
|
574
|
+
"""
|
|
575
|
+
Executes the agent with a message string and returns the final result.
|
|
576
|
+
|
|
577
|
+
This method consumes the entire step() generator and returns only the final
|
|
578
|
+
AgentResponse. Use this when you don't need intermediate streaming responses
|
|
579
|
+
and just want the final output.
|
|
580
|
+
|
|
581
|
+
Args:
|
|
582
|
+
input_ (str): The user input/query for the agent to process
|
|
583
|
+
|
|
584
|
+
Returns:
|
|
585
|
+
AgentResponse: Structured response containing:
|
|
586
|
+
- final_output: The final text or structured output from the LLM
|
|
587
|
+
- state: Current agent state after execution
|
|
588
|
+
- tool_responses: List of all tool calls and their outputs
|
|
589
|
+
- agent_responses: List of linked agent calls (if any)
|
|
590
|
+
- provider_info: Information about the LLM provider used
|
|
591
|
+
|
|
592
|
+
Example:
|
|
593
|
+
```python
|
|
594
|
+
agent = MyAgent(model="openai::gpt-4o", api_key=API_KEY)
|
|
595
|
+
response = await agent.run("What's the weather in San Francisco?")
|
|
596
|
+
print(response.final_output) # LLM's final answer
|
|
597
|
+
print(response.tool_responses) # Tools that were called
|
|
598
|
+
```
|
|
599
|
+
"""
|
|
610
600
|
final_response = None
|
|
611
601
|
async for res in self.step(input_):
|
|
612
602
|
final_response = res
|
|
@@ -614,13 +604,57 @@ class BaseAgent(metaclass=AgentMeta):
|
|
|
614
604
|
|
|
615
605
|
async def __call__(self, user_input: str) -> BaseModel:
|
|
616
606
|
"""
|
|
617
|
-
|
|
607
|
+
Customizable callable interface for the agent. Override this method to accept
|
|
608
|
+
structured, typed parameters that match your agent's purpose.
|
|
609
|
+
|
|
610
|
+
When this agent is linked to another agent, the parameters of this method become
|
|
611
|
+
the tool parameters that the LLM sees. This enables type-safe, structured agent
|
|
612
|
+
composition in multi-agent systems.
|
|
613
|
+
|
|
614
|
+
The default implementation accepts a single user_input string and forwards it to
|
|
615
|
+
run(). Override to provide a custom interface:
|
|
618
616
|
|
|
619
617
|
Args:
|
|
620
|
-
user_input (str): The user input to process
|
|
618
|
+
user_input (str): The user input to process (default implementation)
|
|
621
619
|
|
|
622
620
|
Returns:
|
|
623
621
|
AgentResponse: The agent's response
|
|
622
|
+
|
|
623
|
+
Example (Default Usage):
|
|
624
|
+
```python
|
|
625
|
+
agent = MyAgent(model="openai::gpt-4o", api_key=API_KEY)
|
|
626
|
+
response = await agent("What's the weather?")
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
Example (Custom Implementation):
|
|
630
|
+
```python
|
|
631
|
+
class CoursePlannerAgent(BaseAgent):
|
|
632
|
+
__system_message__ = "You design course curricula"
|
|
633
|
+
__description__ = "Creates structured course plans"
|
|
634
|
+
|
|
635
|
+
async def __call__(
|
|
636
|
+
self,
|
|
637
|
+
goal: str,
|
|
638
|
+
experience: str,
|
|
639
|
+
context: Optional[str] = None
|
|
640
|
+
) -> CoursePlan:
|
|
641
|
+
# Build structured prompt from parameters
|
|
642
|
+
prompt = f"Goal: {goal}\\nExperience: {experience}"
|
|
643
|
+
if context:
|
|
644
|
+
prompt += f"\\nContext: {context}"
|
|
645
|
+
return await self.run(prompt)
|
|
646
|
+
|
|
647
|
+
# Call with structured parameters
|
|
648
|
+
planner = CoursePlannerAgent(model="openai::gpt-4o", api_key=API_KEY)
|
|
649
|
+
course = await planner(
|
|
650
|
+
goal="Learn ML",
|
|
651
|
+
experience="Python beginner",
|
|
652
|
+
context="Prefer hands-on projects"
|
|
653
|
+
)
|
|
654
|
+
|
|
655
|
+
# When linked to another agent, the LLM sees:
|
|
656
|
+
# Tool: planner(goal: str, experience: str, context: Optional[str])
|
|
657
|
+
```
|
|
624
658
|
"""
|
|
625
659
|
return await self.run(input_=user_input)
|
|
626
660
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pyagentic_core-2.1.0a2 → pyagentic_core-2.1.0a3}/pyagentic_core.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|