Skip to content

Commit 67c0625

Browse files
committed
fix: package agent as proper python module
Previously, we ran with src/ as the working directory and hacked PYTHONPATH to resolve local dependencies. Instead, make the cx-agent-backend a buildable Python package with a runnable entrypoint.
1 parent 6564f3a commit 67c0625

31 files changed

+108
-102
lines changed

cx-agent-backend/Dockerfile

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,16 @@ WORKDIR /app
88
ENV UV_PROJECT_ENVIRONMENT="/usr/local/"
99
ENV UV_COMPILE_BYTECODE=1
1010

11-
# Copy dependency configuration and install Python dependencies
12-
COPY pyproject.toml .
13-
RUN uv sync
11+
# Install dependencies only (so this step can be cached if only source files are changed):
12+
COPY pyproject.toml uv.lock ./
13+
RUN uv sync --no-dev --no-install-local
1414

15-
# Copy application source code
16-
COPY src/ ./src/
17-
18-
# Set Python path
19-
ENV PYTHONPATH="/app/src"
15+
# Copy and install the agent source code itself:
16+
COPY cx_agent_backend ./cx_agent_backend
17+
RUN uv sync --no-dev
2018

2119
# Expose FastAPI server port
2220
EXPOSE 8080
2321

2422
# Start the CX Agent service
25-
CMD ["opentelemetry-instrument", "python", "src/run.py"]
23+
CMD ["opentelemetry-instrument", "python", "-m", "cx_agent_backend"]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"""CX demo agent package including agent definition and AgentCore-compatible REST server"""
2+
3+
# Configure structured logging here during module initialization, before other local and external
4+
# imports start creating loggers:
5+
import structlog
6+
7+
structlog.configure(
8+
processors=[
9+
structlog.stdlib.filter_by_level,
10+
structlog.stdlib.add_logger_name,
11+
structlog.stdlib.add_log_level,
12+
structlog.stdlib.PositionalArgumentsFormatter(),
13+
structlog.processors.TimeStamper(fmt="iso"),
14+
structlog.processors.StackInfoRenderer(),
15+
structlog.processors.format_exc_info,
16+
structlog.processors.UnicodeDecoder(),
17+
structlog.processors.JSONRenderer(),
18+
],
19+
context_class=dict,
20+
logger_factory=structlog.stdlib.LoggerFactory(),
21+
cache_logger_on_first_use=True,
22+
)
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""Main entrypoint for running the agent server (uvicorn-fronted FastAPI)"""
2+
3+
import uvicorn
4+
5+
from cx_agent_backend.infrastructure.config.settings import settings
6+
from cx_agent_backend.server import create_app
7+
8+
uvicorn.run(
9+
create_app(),
10+
host=settings.host,
11+
port=settings.port,
12+
reload=settings.debug,
13+
log_level=settings.log_level.lower(),
14+
)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Domain layer"""

cx-agent-backend/src/domain/entities/conversation.py renamed to cx-agent-backend/cx_agent_backend/domain/entities/conversation.py

File renamed without changes.

cx-agent-backend/src/domain/ports/secret_reader.py renamed to cx-agent-backend/cx_agent_backend/domain/ports/secret_reader.py

File renamed without changes.

cx-agent-backend/src/domain/repositories/conversation_repository.py renamed to cx-agent-backend/cx_agent_backend/domain/repositories/conversation_repository.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from abc import ABC, abstractmethod
44
from uuid import UUID
55

6-
from domain.entities.conversation import Conversation
6+
from cx_agent_backend.domain.entities.conversation import Conversation
77

88

99
class ConversationRepository(ABC):

cx-agent-backend/src/domain/services/agent_service.py renamed to cx-agent-backend/cx_agent_backend/domain/services/agent_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from dataclasses import dataclass
55
from enum import Enum
66

7-
from domain.entities.conversation import Message
7+
from cx_agent_backend.domain.entities.conversation import Message
88

99

1010
class AgentType(str, Enum):

cx-agent-backend/src/domain/services/conversation_service.py renamed to cx-agent-backend/cx_agent_backend/domain/services/conversation_service.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66

77
from langfuse import get_client, Langfuse
88

9-
from domain.entities.conversation import Conversation, Message
10-
from domain.repositories.conversation_repository import ConversationRepository
11-
from domain.services.agent_service import AgentRequest, AgentService, AgentType
12-
from domain.services.guardrail_service import GuardrailAssessment, GuardrailService
9+
from cx_agent_backend.domain.entities.conversation import Conversation, Message
10+
from cx_agent_backend.domain.repositories.conversation_repository import ConversationRepository
11+
from cx_agent_backend.domain.services.agent_service import AgentRequest, AgentService, AgentType
12+
from cx_agent_backend.domain.services.guardrail_service import GuardrailAssessment, GuardrailService
1313

1414
logger = logging.getLogger(__name__)
1515

cx-agent-backend/src/domain/services/guardrail_service.py renamed to cx-agent-backend/cx_agent_backend/domain/services/guardrail_service.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from dataclasses import dataclass
55
from enum import Enum
66

7-
from domain.entities.conversation import Message
7+
from cx_agent_backend.domain.entities.conversation import Message
88

99

1010
class GuardrailAssessment(str, Enum):

0 commit comments

Comments
 (0)