|
4 | 4 | from pydantic import TypeAdapter |
5 | 5 |
|
6 | 6 | from uipath.agent.models.agent import ( |
| 7 | + AgentA2aResourceConfig, |
7 | 8 | AgentBooleanOperator, |
8 | 9 | AgentBooleanRule, |
9 | 10 | AgentBuiltInValidatorGuardrail, |
@@ -3528,3 +3529,216 @@ def test_datafabric_entity_identifiers_empty(self): |
3528 | 3529 | } |
3529 | 3530 | parsed = AgentContextResourceConfig.model_validate(config) |
3530 | 3531 | assert parsed.datafabric_entity_identifiers == [] |
| 3532 | + |
| 3533 | + def test_a2a_resource(self): |
| 3534 | + """Test that AgentDefinition can load A2A resources.""" |
| 3535 | + |
| 3536 | + json_data = { |
| 3537 | + "version": "1.0.0", |
| 3538 | + "id": "test-a2a-resource", |
| 3539 | + "name": "Agent with A2A Resource", |
| 3540 | + "metadata": {"isConversational": False, "storageVersion": "36.0.0"}, |
| 3541 | + "messages": [ |
| 3542 | + {"role": "System", "content": "You are an agentic assistant."} |
| 3543 | + ], |
| 3544 | + "inputSchema": {"type": "object", "properties": {}}, |
| 3545 | + "outputSchema": {"type": "object", "properties": {}}, |
| 3546 | + "settings": { |
| 3547 | + "model": "gpt-4o-2024-11-20", |
| 3548 | + "maxTokens": 16384, |
| 3549 | + "temperature": 0, |
| 3550 | + "engine": "basic-v2", |
| 3551 | + }, |
| 3552 | + "resources": [ |
| 3553 | + { |
| 3554 | + "$resourceType": "a2a", |
| 3555 | + "id": "755e2f7d-5a3d-47f3-8e9d-7ff0bf226357", |
| 3556 | + "name": "Philosopher Agent", |
| 3557 | + "slug": "philosopher-agent", |
| 3558 | + "description": "A philosophical agent that answers questions with wisdom and philosopher quotes", |
| 3559 | + "agentCardUrl": "", |
| 3560 | + "isActive": True, |
| 3561 | + "cachedAgentCard": { |
| 3562 | + "name": "Philosopher Agent", |
| 3563 | + "description": "Philosopher Agent assistant", |
| 3564 | + "url": "https://philosopher-agent.example.com/a2a/5045dca3", |
| 3565 | + "supportedInterfaces": [ |
| 3566 | + { |
| 3567 | + "url": "https://philosopher-agent.example.com/a2a/5045dca3", |
| 3568 | + "protocolBinding": "jsonrpc", |
| 3569 | + "protocolVersion": "1.0", |
| 3570 | + } |
| 3571 | + ], |
| 3572 | + "capabilities": { |
| 3573 | + "streaming": True, |
| 3574 | + "pushNotifications": False, |
| 3575 | + "stateTransitionHistory": False, |
| 3576 | + }, |
| 3577 | + "defaultInputModes": [ |
| 3578 | + "application/json", |
| 3579 | + "text/plain", |
| 3580 | + ], |
| 3581 | + "defaultOutputModes": [ |
| 3582 | + "application/json", |
| 3583 | + "text/plain", |
| 3584 | + ], |
| 3585 | + "skills": [ |
| 3586 | + { |
| 3587 | + "id": "5045dca3-main", |
| 3588 | + "name": "Philosopher Agent Capabilities", |
| 3589 | + "description": "Philosopher Agent assistant", |
| 3590 | + "tags": ["assistant", "langgraph"], |
| 3591 | + "examples": [], |
| 3592 | + "inputModes": [ |
| 3593 | + "application/json", |
| 3594 | + "text/plain", |
| 3595 | + ], |
| 3596 | + "outputModes": [ |
| 3597 | + "application/json", |
| 3598 | + "text/plain", |
| 3599 | + ], |
| 3600 | + "metadata": { |
| 3601 | + "inputSchema": { |
| 3602 | + "required": ["messages"], |
| 3603 | + "properties": ["messages"], |
| 3604 | + "supportsA2A": True, |
| 3605 | + } |
| 3606 | + }, |
| 3607 | + } |
| 3608 | + ], |
| 3609 | + "version": "0.7.70", |
| 3610 | + }, |
| 3611 | + "createdAt": "2026-03-15T10:12:47.9073065", |
| 3612 | + "createdBy": "f4bc4946-baed-4083-82b9-03d334bbacbe", |
| 3613 | + "updatedAt": None, |
| 3614 | + "updatedBy": None, |
| 3615 | + } |
| 3616 | + ], |
| 3617 | + "features": [], |
| 3618 | + "guardrails": [], |
| 3619 | + } |
| 3620 | + |
| 3621 | + config: AgentDefinition = TypeAdapter(AgentDefinition).validate_python( |
| 3622 | + json_data |
| 3623 | + ) |
| 3624 | + |
| 3625 | + # Validate A2A resource |
| 3626 | + a2a_resources = [ |
| 3627 | + r for r in config.resources if r.resource_type == AgentResourceType.A2A |
| 3628 | + ] |
| 3629 | + assert len(a2a_resources) == 1 |
| 3630 | + a2a_resource = a2a_resources[0] |
| 3631 | + assert isinstance(a2a_resource, AgentA2aResourceConfig) |
| 3632 | + assert a2a_resource.name == "Philosopher Agent" |
| 3633 | + assert a2a_resource.slug == "philosopher-agent" |
| 3634 | + assert ( |
| 3635 | + a2a_resource.description |
| 3636 | + == "A philosophical agent that answers questions with wisdom and philosopher quotes" |
| 3637 | + ) |
| 3638 | + assert a2a_resource.is_active is True |
| 3639 | + assert a2a_resource.agent_card_url == "" |
| 3640 | + assert a2a_resource.id == "755e2f7d-5a3d-47f3-8e9d-7ff0bf226357" |
| 3641 | + assert a2a_resource.created_at == "2026-03-15T10:12:47.9073065" |
| 3642 | + assert a2a_resource.created_by == "f4bc4946-baed-4083-82b9-03d334bbacbe" |
| 3643 | + assert a2a_resource.updated_at is None |
| 3644 | + assert a2a_resource.updated_by is None |
| 3645 | + |
| 3646 | + # Validate cached agent card is a plain dict |
| 3647 | + card = a2a_resource.cached_agent_card |
| 3648 | + assert isinstance(card, dict) |
| 3649 | + assert card["name"] == "Philosopher Agent" |
| 3650 | + assert card["url"] == "https://philosopher-agent.example.com/a2a/5045dca3" |
| 3651 | + assert card["version"] == "0.7.70" |
| 3652 | + assert len(card["supportedInterfaces"]) == 1 |
| 3653 | + assert card["supportedInterfaces"][0]["protocolBinding"] == "jsonrpc" |
| 3654 | + assert card["capabilities"]["streaming"] is True |
| 3655 | + assert len(card["skills"]) == 1 |
| 3656 | + assert card["skills"][0]["name"] == "Philosopher Agent Capabilities" |
| 3657 | + |
| 3658 | + def test_a2a_resource_without_cached_card(self): |
| 3659 | + """Test A2A resource with no cachedAgentCard.""" |
| 3660 | + |
| 3661 | + json_data = { |
| 3662 | + "version": "1.0.0", |
| 3663 | + "id": "test-a2a-no-card", |
| 3664 | + "name": "Agent with minimal A2A", |
| 3665 | + "metadata": {"isConversational": False, "storageVersion": "36.0.0"}, |
| 3666 | + "messages": [{"role": "System", "content": "You are an assistant."}], |
| 3667 | + "inputSchema": {"type": "object", "properties": {}}, |
| 3668 | + "outputSchema": {"type": "object", "properties": {}}, |
| 3669 | + "settings": { |
| 3670 | + "model": "gpt-4o-2024-11-20", |
| 3671 | + "maxTokens": 16384, |
| 3672 | + "temperature": 0, |
| 3673 | + "engine": "basic-v2", |
| 3674 | + }, |
| 3675 | + "resources": [ |
| 3676 | + { |
| 3677 | + "$resourceType": "a2a", |
| 3678 | + "id": "abc-123", |
| 3679 | + "name": "Minimal A2A Agent", |
| 3680 | + "slug": "minimal-a2a", |
| 3681 | + "description": "A minimal A2A agent", |
| 3682 | + "isActive": False, |
| 3683 | + } |
| 3684 | + ], |
| 3685 | + "features": [], |
| 3686 | + "guardrails": [], |
| 3687 | + } |
| 3688 | + |
| 3689 | + config: AgentDefinition = TypeAdapter(AgentDefinition).validate_python( |
| 3690 | + json_data |
| 3691 | + ) |
| 3692 | + |
| 3693 | + a2a_resources = [ |
| 3694 | + r for r in config.resources if r.resource_type == AgentResourceType.A2A |
| 3695 | + ] |
| 3696 | + assert len(a2a_resources) == 1 |
| 3697 | + a2a_resource = a2a_resources[0] |
| 3698 | + assert isinstance(a2a_resource, AgentA2aResourceConfig) |
| 3699 | + assert a2a_resource.name == "Minimal A2A Agent" |
| 3700 | + assert a2a_resource.slug == "minimal-a2a" |
| 3701 | + assert a2a_resource.is_active is False |
| 3702 | + assert a2a_resource.cached_agent_card is None |
| 3703 | + assert a2a_resource.agent_card_url == "" |
| 3704 | + assert a2a_resource.created_at is None |
| 3705 | + |
| 3706 | + def test_a2a_resource_case_insensitive(self): |
| 3707 | + """Test that A2A resource type is parsed case-insensitively.""" |
| 3708 | + |
| 3709 | + json_data = { |
| 3710 | + "version": "1.0.0", |
| 3711 | + "id": "test-a2a-case", |
| 3712 | + "name": "Agent A2A case test", |
| 3713 | + "metadata": {"isConversational": False, "storageVersion": "36.0.0"}, |
| 3714 | + "messages": [{"role": "System", "content": "You are an assistant."}], |
| 3715 | + "inputSchema": {"type": "object", "properties": {}}, |
| 3716 | + "outputSchema": {"type": "object", "properties": {}}, |
| 3717 | + "settings": { |
| 3718 | + "model": "gpt-4o-2024-11-20", |
| 3719 | + "maxTokens": 16384, |
| 3720 | + "temperature": 0, |
| 3721 | + "engine": "basic-v2", |
| 3722 | + }, |
| 3723 | + "resources": [ |
| 3724 | + { |
| 3725 | + "$resourceType": "A2A", |
| 3726 | + "id": "case-test-id", |
| 3727 | + "name": "Case Test Agent", |
| 3728 | + "slug": "case-test", |
| 3729 | + "description": "Testing case insensitive parsing", |
| 3730 | + } |
| 3731 | + ], |
| 3732 | + "features": [], |
| 3733 | + "guardrails": [], |
| 3734 | + } |
| 3735 | + |
| 3736 | + config: AgentDefinition = TypeAdapter(AgentDefinition).validate_python( |
| 3737 | + json_data |
| 3738 | + ) |
| 3739 | + |
| 3740 | + a2a_resources = [ |
| 3741 | + r for r in config.resources if r.resource_type == AgentResourceType.A2A |
| 3742 | + ] |
| 3743 | + assert len(a2a_resources) == 1 |
| 3744 | + assert isinstance(a2a_resources[0], AgentA2aResourceConfig) |
0 commit comments