Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ async def http_start(req: func.HttpRequest, client: df.DurableOrchestrationClien
request_response_format,
)
logger.debug("Signalling entity %s with request: %s", entity_instance_id, run_request)
await client.signal_entity(entity_instance_id, "run_agent", run_request)
await client.signal_entity(entity_instance_id, "run", run_request)

logger.debug(f"[HTTP Trigger] Signal sent to entity {session_id}")

Expand Down Expand Up @@ -495,7 +495,8 @@ def entity_function(context: df.DurableEntityContext) -> None:
"""Durable entity that manages agent execution and conversation state.

Operations:
- run_agent: Execute the agent with a message
- run: Execute the agent with a message
- run_async: (Deprecated) Execute the agent with a message
- reset: Clear conversation history
"""
entity_handler = create_agent_entity(agent, callback)
Expand Down Expand Up @@ -637,7 +638,7 @@ async def _handle_mcp_tool_invocation(
logger.info("[MCP Tool] Invoking agent '%s' with query: %s", agent_name, query_preview)

# Signal entity to run agent
await client.signal_entity(entity_instance_id, "run_agent", run_request)
await client.signal_entity(entity_instance_id, "run", run_request)

# Poll for response (similar to HTTP handler)
try:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ class AgentEntity:
- Handles tool execution

Operations:
- run_agent: Execute the agent with a message
- run: Execute the agent with a message
- run_agent: (Deprecated) Execute the agent with a message
- reset: Clear conversation history

Attributes:
Expand Down Expand Up @@ -94,6 +95,22 @@ async def run_agent(
self,
context: df.DurableEntityContext,
request: RunRequest | dict[str, Any] | str,
) -> AgentRunResponse:
"""(Deprecated) Execute the agent with a message directly in the entity.

Args:
context: Entity context
request: RunRequest object, dict, or string message (for backward compatibility)

Returns:
AgentRunResponse enriched with execution metadata.
"""
return await self.run(context, request)

async def run(
self,
context: df.DurableEntityContext,
request: RunRequest | dict[str, Any] | str,
) -> AgentRunResponse:
"""Execute the agent with a message directly in the entity.

Expand Down Expand Up @@ -124,7 +141,7 @@ async def run_agent(
state_request = DurableAgentStateRequest.from_run_request(run_request)
self.state.data.conversation_history.append(state_request)

logger.debug(f"[AgentEntity.run_agent] Received Message: {state_request}")
logger.debug(f"[AgentEntity.run] Received Message: {state_request}")

try:
# Build messages from conversation history, excluding error responses
Expand All @@ -150,7 +167,7 @@ async def run_agent(
)

logger.debug(
"[AgentEntity.run_agent] Agent invocation completed - response type: %s",
"[AgentEntity.run] Agent invocation completed - response type: %s",
type(agent_run_response).__name__,
)

Expand All @@ -167,12 +184,12 @@ async def run_agent(
state_response = DurableAgentStateResponse.from_run_response(correlation_id, agent_run_response)
self.state.data.conversation_history.append(state_response)

logger.debug("[AgentEntity.run_agent] AgentRunResponse stored in conversation history")
logger.debug("[AgentEntity.run] AgentRunResponse stored in conversation history")

return agent_run_response

except Exception as exc:
logger.exception("[AgentEntity.run_agent] Agent execution failed.")
logger.exception("[AgentEntity.run] Agent execution failed.")

# Create error message
error_message = ChatMessage(
Expand Down Expand Up @@ -367,7 +384,7 @@ async def _entity_coroutine(context: df.DurableEntityContext) -> None:

operation = context.operation_name

if operation == "run_agent":
if operation == "run" or operation == "run_async":
input_data: Any = context.get_input()

request: str | dict[str, Any]
Expand All @@ -377,7 +394,7 @@ async def _entity_coroutine(context: df.DurableEntityContext) -> None:
# Fall back to treating input as message string
request = "" if input_data is None else str(cast(object, input_data))

result = await entity.run_agent(context, request)
result = await entity.run(context, request)
context.set_result(result.to_dict())

elif operation == "reset":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ def my_orchestration(context):
logger.debug("[DurableAIAgent] Calling entity %s with message: %s", entity_id, message_str[:100])

# Call the entity to get the underlying task
entity_task = self.context.call_entity(entity_id, "run_agent", run_request.to_dict())
entity_task = self.context.call_entity(entity_id, "run", run_request.to_dict())

# Wrap it in an AgentTask that will convert the result to AgentRunResponse
agent_task = AgentTask(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ docker run -d -p 10000:10000 -p 10001:10001 -p 10002:10002 mcr.microsoft.com/azu

**Durable Task Scheduler:**
```bash
docker run -d -p 8080:8080 -p 8082:8082 mcr.microsoft.com/dts/dts-emulator:latest
docker run -d -p 8080:8080 -p 8082:8082 -e DTS_USE_DYNAMIC_TASK_HUBS=true mcr.microsoft.com/dts/dts-emulator:latest
```

## Running Tests
Expand Down
42 changes: 34 additions & 8 deletions python/packages/azurefunctions/tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,7 @@ async def test_entity_run_agent_operation(self) -> None:
entity = AgentEntity(mock_agent)
mock_context = Mock()

result = await entity.run_agent(
result = await entity.run(
mock_context,
{"message": "Test message", "thread_id": "test-conv-123", "correlationId": "corr-app-entity-1"},
)
Expand All @@ -358,7 +358,7 @@ async def test_entity_stores_conversation_history(self) -> None:
mock_context = Mock()

# Send first message
await entity.run_agent(
await entity.run(
mock_context, {"message": "Message 1", "thread_id": "conv-1", "correlationId": "corr-app-entity-2"}
)

Expand All @@ -367,7 +367,7 @@ async def test_entity_stores_conversation_history(self) -> None:
assert len(history) == 1 # Just the user message

# Send second message
await entity.run_agent(
await entity.run(
mock_context, {"message": "Message 2", "thread_id": "conv-2", "correlationId": "corr-app-entity-2b"}
)

Expand Down Expand Up @@ -398,12 +398,12 @@ async def test_entity_increments_message_count(self) -> None:

assert len(entity.state.data.conversation_history) == 0

await entity.run_agent(
await entity.run(
mock_context, {"message": "Message 1", "thread_id": "conv-1", "correlationId": "corr-app-entity-3a"}
)
assert len(entity.state.data.conversation_history) == 2

await entity.run_agent(
await entity.run(
mock_context, {"message": "Message 2", "thread_id": "conv-1", "correlationId": "corr-app-entity-3b"}
)
assert len(entity.state.data.conversation_history) == 4
Expand Down Expand Up @@ -433,8 +433,34 @@ def test_create_agent_entity_returns_function(self) -> None:

assert callable(entity_function)

def test_entity_function_handles_run_operation(self) -> None:
"""Test that the entity function handles the run operation."""
mock_agent = Mock()
mock_agent.run = AsyncMock(
return_value=AgentRunResponse(messages=[ChatMessage(role="assistant", text="Response")])
)

entity_function = create_agent_entity(mock_agent)

# Mock context
mock_context = Mock()
mock_context.operation_name = "run"
mock_context.get_input.return_value = {
"message": "Test message",
"thread_id": "conv-123",
"correlationId": "corr-app-factory-1",
}
mock_context.get_state.return_value = None

# Execute entity function
entity_function(mock_context)

# Verify result was set
assert mock_context.set_result.called
assert mock_context.set_state.called

def test_entity_function_handles_run_agent_operation(self) -> None:
"""Test that the entity function handles the run_agent operation."""
"""Test that the entity function handles the run operation."""
mock_agent = Mock()
mock_agent.run = AsyncMock(
return_value=AgentRunResponse(messages=[ChatMessage(role="assistant", text="Response")])
Expand Down Expand Up @@ -585,7 +611,7 @@ async def test_entity_handles_agent_error(self) -> None:
entity = AgentEntity(mock_agent)
mock_context = Mock()

result = await entity.run_agent(
result = await entity.run(
mock_context, {"message": "Test message", "thread_id": "conv-1", "correlationId": "corr-app-error-1"}
)

Expand All @@ -605,7 +631,7 @@ def test_entity_function_handles_exception(self) -> None:
entity_function = create_agent_entity(mock_agent)

mock_context = Mock()
mock_context.operation_name = "run_agent"
mock_context.operation_name = "run"
mock_context.get_input.side_effect = Exception("Input error")
mock_context.get_state.return_value = None

Expand Down
Loading
Loading