Internal Documentation internal
TalkIDE internal documentation

Start a new conversation with the AI PM by sending the first message. Only the project owner can start a conversation. The project must not be ARCHIVED.

  • Starting a new conversation automatically closes the current ACTIVE conversation for this project (if any) — its status is set to CLOSED.
  • A project can have at most one ACTIVE conversation at a time (MVP constraint).
  • The conversation title is auto-generated from the first message: the first 50 characters, trimmed at the last word boundary so no word is cut off.
  • After creating the USER message, a mock PM response is created immediately (since AI is not integrated yet). The mock response simulates a realistic PM acknowledgement. The API contract is designed so that real AI integration can replace the mock later without any changes to the API.
  • The response includes the newly created conversation with its messages array (both the USER message and the mock PM response).
  • An ARCHIVED project cannot start a new conversation.

Auto-start variant (called from UC-03002)

StartConversationUseCase is also invoked internally by UC-03002 Create Project immediately after a project is created. This variant differs from the standard “user types first message” flow described above:

  • No message is supplied → no USER message is persisted, no mock PM message is generated.
  • Conversation is created with status = ACTIVE, title = "New project" (i18n fallback; re-titled later from the first real exchange), sessionId = null.
  • Runs in the same transaction as the project insert — if conversation creation fails, project insert rolls back.
  • The newly returned conversationId is included in the CreateProjectResponse.

After the FE navigates to /workspace/:projectId and loads this empty conversation, it triggers Mara’s opening message via SSE without any user input. Mara uses the project’s description and tech-stack fields (rendered into CLAUDE.md per mara-context.md) as context, does not greet the user (Pseudo-Mara already did during the create flow), and asks a short focused question about today’s work.

Note: the standard “user types first message” flow described below still applies for all subsequent Start Conversation calls (e.g. closing the current ACTIVE conversation and starting a fresh one mid-project).

sequenceDiagram
    actor User

    User->>+FE: types first message and submits

    FE->>FE: validate form
    alt form is invalid
        FE-->>User: show error messages <br> disable submit button
    end

    FE->>+BE: POST /api/v1/projects/{projectId}/conversations <br> Authorization: Bearer {accessToken} <br> StartConversationRequest

    BE->>BE: validate access token
    alt token missing or invalid
        BE-->>FE: 401 Unauthorized <br> ErrorResponse
    end

    BE->>DB: load project by projectId
    alt project not found
        BE-->>FE: 404 Not Found <br> ErrorResponse
    end

    BE->>BE: check project belongs to user's tenant
    alt project does not belong to tenant
        BE-->>FE: 403 Forbidden <br> ErrorResponse
    end

    BE->>BE: check project is not ARCHIVED
    alt project is ARCHIVED
        BE-->>FE: 409 Conflict <br> ErrorResponse
    end

    BE->>BE: validate request body
    alt request is invalid
        BE-->>FE: 400 Bad Request <br> ErrorResponse
    end

    BE->>DB: find current ACTIVE conversation for project (if any)
    alt ACTIVE conversation exists
        BE->>DB: set existing conversation status = CLOSED
    end

    BE->>DB: insert new conversation (status = ACTIVE, title = auto-generated)

    BE->>DB: insert USER message

    BE->>BE: generate mock PM response

    BE->>DB: insert PM message

    BE->>-FE: 201 Created <br> ConversationDetailResponse

    FE->>-User: open conversation view with messages

POST /api/v1/projects/{projectId}/conversations StartConversationRequest:

{
  "message": "I want to add a contact form to the homepage with name, email, and message fields."
}

201 Created ConversationDetailResponse:

{
  "data": {
    "id": 8,
    "title": "I want to add a contact form to the homepage",
    "status": "ACTIVE",
    "messageCount": 2,
    "createdAt": "2026-04-29T12:00:00Z",
    "updatedAt": "2026-04-29T12:00:01Z",
    "messages": [
      {
        "id": 21,
        "role": "USER",
        "content": "I want to add a contact form to the homepage with name, email, and message fields.",
        "createdAt": "2026-04-29T12:00:00Z"
      },
      {
        "id": 22,
        "role": "PM",
        "content": "Great idea! I understand your request. Let me analyze the homepage structure and plan the contact form implementation. I'll get back to you with a detailed plan shortly.",
        "createdAt": "2026-04-29T12:00:01Z"
      }
    ]
  }
}

400 Bad Request (validation) ErrorResponse:

{
  "status": 400,
  "code": "VALIDATION_ERROR",
  "message": "Validation failed",
  "errors": [
    { "field": "message", "message": "must not be blank" }
  ]
}

401 Unauthorized (missing or invalid access token) ErrorResponse:

{
  "status": 401,
  "code": "AUTHENTICATION_FAILED",
  "message": "Access token is missing or invalid"
}

403 Forbidden (project does not belong to user’s tenant) ErrorResponse:

{
  "status": 403,
  "code": "FORBIDDEN",
  "message": "You do not have access to this project"
}

404 Not Found (project not found) ErrorResponse:

{
  "status": 404,
  "code": "NOT_FOUND_PROJECT",
  "message": "Project not found"
}

409 Conflict (project is ARCHIVED) ErrorResponse:

{
  "status": 409,
  "code": "CONFLICT_PROJECT",
  "message": "Cannot start a conversation on an ARCHIVED project"
}

Frontend

Validations

FieldConstraintsSizePatternNote
messagenot_blank1 - 5000

Backend

Validations

FieldConstraintsSizePatternNote
projectIdnot_null, positivePath variable; must reference an existing project
messagenot_blank1 - 5000First user message; used for auto-generating conversation title

Mock PM Responses

The backend selects one of the following mock responses when creating the PM message. The selection can be random or sequential. This list will be replaced by real AI integration in a future iteration:

  1. “Great idea! I understand your request. Let me analyze the project structure and plan the implementation. I’ll outline the necessary changes shortly.”
  2. “Got it. I’m reviewing your requirements now. This looks like an interesting challenge — let me think through the best approach and come back to you with a plan.”
  3. “Understood! I’ve noted your request and I’m already thinking about how to approach this. Give me a moment to analyze the current state of the project.”
  4. “Perfect, I have a clear picture of what you need. Let me work through the details and prepare a step-by-step plan for this change.”

Test Cases

GIVENWHENTHEN
authenticated user, active project, no existing conversationPOST /projects/{projectId}/conversations is called201 Created with new conversation (ACTIVE), USER and PM messages returned
authenticated user, active project, existing ACTIVE conversationPOST /projects/{projectId}/conversations is calledexisting conversation is closed, new conversation created, 201 Created returned
authenticated user, ARCHIVED projectPOST /projects/{projectId}/conversations is called409 CONFLICT_PROJECT error response is returned
authenticated user, project does not existPOST /projects/{projectId}/conversations is called404 NOT_FOUND_PROJECT error response is returned
authenticated user, project belongs to a different tenantPOST /projects/{projectId}/conversations is called403 FORBIDDEN error response is returned
message is blankPOST /projects/{projectId}/conversations is called400 VALIDATION_ERROR error response is returned
message longer than 5000 charactersPOST /projects/{projectId}/conversations is called400 VALIDATION_ERROR error response is returned
no Authorization headerPOST /projects/{projectId}/conversations is called401 AUTHENTICATION_FAILED error response is returned
first message exactly 50 charactersPOST /projects/{projectId}/conversations is called201 Created; conversation title equals the message content exactly
first message longer than 50 charactersPOST /projects/{projectId}/conversations is called201 Created; conversation title is trimmed at word boundary within first 50 chars
project just created (auto-start variant from UC-03002)StartConversationUseCase.autoStart(projectId) is invoked internallyconversation created with status=ACTIVE, title=“New project”, no USER message, no mock PM message, sessionId=null
auto-start variant; underlying DB insert failsStartConversationUseCase.autoStart(projectId) is invoked internallyexception propagates; outer Create Project transaction rolls back

Was this page helpful?

Thanks for the feedback.