Conversational AI agent for job discovery on the inmates.ai platform. This service provides a natural language interface for users to discover and explore job listings.
The Career Advocate is a standalone API service that:
- Provides a conversational chat interface for job discovery
- Integrates with the inmates-backend API for job data
- Uses LangChain TypeScript for AI agent capabilities
- Validates and forwards JWT tokens for authentication
Frontend → Career Advocate API → Inmates Backend API
- Frontend calls Career Advocate endpoints (e.g.,
POST /api/chat) - Career Advocate validates JWT tokens and forwards them to the backend
- Backend returns job data which the agent processes and formats conversationally
- Node.js >= 18.0.0
- npm or yarn
- Access to inmates-backend API
- OpenAI API key (or alternative LLM provider)
-
Clone the repository
-
Install dependencies:
npm install
-
Copy environment variables:
cp .env.example .env
-
Configure
.envfile with your settings:BACKEND_API_BASE_URL: Your inmates-backend API URLJWT_SECRET: Must match the JWT secret used by inmates-backendOPENAI_API_KEY: Your OpenAI API keyPORT: Server port (default: 3001)
Run in development mode with hot reload:
npm run devBuild for production:
npm run buildRun production build:
npm startinmates-career-advocate/
├── src/
│ ├── server/ # API server (Express)
│ ├── agent/ # LangChain agent implementation
│ ├── api/ # Backend API client
│ ├── services/ # Business logic services
│ ├── types/ # TypeScript type definitions
│ └── utils/ # Utility functions
├── dist/ # Compiled output
└── package.json
Send a message to the conversational agent.
Request:
{
"message": "I'm a software engineer, show me remote jobs"
}Headers:
Authorization: Bearer <jwt_token>
Response:
{
"response": "I found 15 remote software engineer positions...",
"conversationId": "conv_123",
"jobs": [...]
}Builds a resume PDF from structured resume content.
Auth requirement:
- Requires
Authorization: Bearer <jwt_token> - Endpoint is protected by JWT auth middleware (same auth flow as
/api/chat)
Request headers:
Authorization: Bearer <jwt_token>
Content-Type: application/json
Accept: application/pdf
Request payload summary:
personalInfo(required):firstName,lastName,email, optionalphone,location,headlinesummaryorobjective(at least one required)experience(required, min 1): role/company/date range, optional highlightseducation(required, min 1)skills(required, min 1)- Optional arrays:
certifications,projects,links(if provided, each must include at least one item) - Unknown fields are rejected at all payload levels (strict schema validation)
Success response (binary PDF):
- Status:
200 OK - Body: raw binary PDF bytes (not JSON)
- Key response headers:
Content-Type: application/pdfContent-Disposition: attachment; filename="<generated-or-default>.pdf"
Validation/auth error response:
- Returns JSON errors (for example
400validation failure,401auth failure)
Health check endpoint.
Response:
{
"status": "healthy",
"timestamp": "2025-01-27T10:00:00Z",
"uptime": 3600
}- Linting:
npm run lint - Formatting:
npm run format - Type Checking:
npm run type-check
Test the connection to the inmates-backend API:
npm run test:apiThis script will:
- Test backend connectivity
- Verify JWT token (if
TEST_JWT_TOKENis set in.env) - Test job search API
- Test job retrieval by ID (if
TEST_JOB_IDis set) - Test filtered search
Setup for testing:
-
Ensure your
.envfile has:BACKEND_API_BASE_URL- Your backend API URLJWT_SECRET- Must match backend JWT secretTEST_JWT_TOKEN(optional, dev-only) - A valid JWT token for local testingTEST_JOB_ID(optional) - A valid job ID for testing
-
Get a JWT token (dev only):
- Log in through the frontend or backend auth endpoint
- Copy the access token
- Add it to
.envasTEST_JWT_TOKEN(local development only) - IMPORTANT: Never set
TEST_JWT_TOKENin staging or production environments
- Resume endpoint integration tests:
npm run test:resume - Full test suite:
npm run test:all
See .env.example for all available configuration options.
Important: TEST_JWT_TOKEN is for local development and testing only. Never set this in staging or production environments. See DEPLOYMENT.md for deployment security guidelines.
Private - Internal use only