AI-powered appointment assistant built with Spring Boot and Spring AI. You can type natural language to:
- book appointments,
- list a user's appointments,
- cancel appointments,
- introduce yourself once and let the assistant remember your name/contact during the current conversation.
- Natural language chat via REST
POST /chat - Natural language interactive CLI mode (
cliprofile) - LLM intent extraction for
BOOK,LIST,DELETE, andIDENTIFY - Spring AI conversation memory via
MessageChatMemoryAdvisor - BOM-based dependency alignment for Spring AI and Jackson
- One conversation context per CLI session
- Stable web conversation context via
X-Conversation-Idor HTTP session fallback - In-memory appointment storage (resets on restart)
- In-memory conversation memory (resets on restart)
- Swagger/OpenAPI documentation
- Java 21
- Spring Boot 4.0.x
- Spring AI 2.0.0 (OpenAI starter, managed via Spring AI BOM)
- Springdoc OpenAPI + Swagger UI
- Lombok
- JDK 21
- Maven 3.9+
- OpenAI API key
-
Open the project.
-
Set API key (PowerShell):
$env:OPENAI_API_KEY="sk-your-key"- Run the app.
REST mode (default):
mvn spring-boot:runCLI mode from PowerShell:
$env:SPRING_PROFILES_ACTIVE="cli"
mvn spring-boot:runCLI mode from Command Prompt (cmd.exe):
set SPRING_PROFILES_ACTIVE=cli
mvn spring-boot:runPackaged jar in CLI mode:
mvn clean package -DskipTests
java -jar target/calendarbot-1.0-SNAPSHOT.jar --spring.profiles.active=cliThe app supports these intents through both REST and CLI:
BOOK: create an appointment- provide service + date + time
- name/contact can come from the current message or remembered conversation context
LIST: list current user's appointments- provide name and/or contact, either directly or from remembered context
DELETE: cancel one appointment- provide date + time and enough identity information to match the booking
IDENTIFY: introduce or correct your name/contact for the current conversation- examples:
I am Yichun,My email is yichun@mail.com
- examples:
Conversation memory is scoped to the current conversation only:
- CLI: one memory window per REPL session
- REST: one memory window per
X-Conversation-Idvalue, or per HTTP session if that header is omitted - Memory is not persisted across application restarts
calendarbot:> I am Yichun
Thanks, Yichun. I'll remember you for this conversation.
calendarbot:> book a cleaning for me on 2026-04-10 at 10:00
Your appointment is scheduled for 2026-04-10 at 10:00
calendarbot:> list my appointments
Appointments for Yichun:
1) 2026-04-10 10:00 - Cleaning
calendarbot:> cancel my appointment on 2026-04-10 at 10:00
Your appointment on 2026-04-10 at 10:00 has been cancelled.
Exit CLI with:
exitquit
POST /chatContent-Type: text/plain- Body: any natural language message
- Optional request header:
X-Conversation-Id - If provided, the same header value should be reused on follow-up requests so the assistant remembers earlier messages
- If omitted, the app falls back to the current HTTP session id
- The response echoes the effective
X-Conversation-Idheader
Single request example:
curl -X POST http://localhost:8080/chat -H "Content-Type: text/plain" -d "list appointments for alice@mail.com"Multi-turn example with remembered identity:
$conversationId = "demo-yichun"
curl -X POST http://localhost:8080/chat `
-H "Content-Type: text/plain" `
-H "X-Conversation-Id: $conversationId" `
-d "I am Yichun"
curl -X POST http://localhost:8080/chat `
-H "Content-Type: text/plain" `
-H "X-Conversation-Id: $conversationId" `
-d "list my appointments"src/main/resources/application.properties:
server.port=8080spring.ai.openai.api-key=${OPENAI_API_KEY}spring.ai.openai.base-url=https://api.openai.comspring.ai.openai.chat.options.model=gpt-4o
Change model example:
spring.ai.openai.chat.options.model=gpt-4o-miniorg.springframework.ai:spring-ai-bomis imported inpom.xmland controlled byspring-ai.version(2.0.0).- Spring Boot dependency versions are managed by
spring-boot-starter-parent(4.0.7). spring-ai-starter-model-openaihas no explicit<version>in dependencies because it is managed by the Spring AI BOM.
- Swagger UI:
http://localhost:8080/swagger-ui/index.html - OpenAPI JSON:
http://localhost:8080/v3/api-docs
CalendarBot- Spring Boot entry pointAiConfig- configuresChatMemoryand the memory-enabledChatClientChatController- REST endpoint for/chat(non-cliprofile), including conversation-id handlingCliRunner- terminal REPL incliprofile; reuses one conversation id for the full sessionChatService- LLM prompt + intent routing (BOOK/LIST/DELETE/IDENTIFY)AppointmentService- booking/listing/cancel contractInMemoryAppointmentService- in-memory implementationAppointmentRequest- DTO used for extraction and scheduling data
mvn clean package
mvn test
mvn org.owasp:dependency-check-maven:check- If you see
No command found for '--spring.profiles.active=cli', set profile via environment variable beforemvn spring-boot:run. - Appointments are in-memory only and reset after restart.
- Conversation memory is also in-memory only and resets after restart or when you start a new CLI process with a fresh conversation id.
- For REST clients, reuse the same
X-Conversation-Idacross related requests if you want the assistant to remember prior turns. - Ensure Maven and IDE both use Java 21.
This project is licensed under the MIT License. See LICENSE.