A2A Protocol

Data Validation

How the system evaluates incoming interview data and routes to INFO_NEEDED or VALIDATING_SKILLS.

When an interview creation request arrives, the DataValidationService evaluates each field against a three-tier severity model. The result determines whether processing proceeds immediately or enters the HITL INFO_NEEDED state for data completion.

Severity Tiers

SeverityImpactState Result
CRITICALCannot proceed without this fieldINFO_NEEDED
HIGHSignificantly degrades plan qualityINFO_NEEDED
MEDIUMMinor quality reductionWarning only — proceeds

Field Rules

FieldSeverityRuleQuestion Sent to HITL
candidateNameCRITICALRequired, non-emptyPlease provide the full name of the candidate
candidateEmailCRITICALRequired, valid email formatPlease provide a valid email address for the candidate
positionCRITICALRequired, non-emptyPlease specify the job position or title
levelHIGHRequired: JUNIOR/MID/SENIOR/LEAD/PRINCIPALPlease specify the seniority level
skillsHIGHAt least 1 skill requiredPlease provide at least one required skill
jobDescriptionHIGHMinimum 50 charactersPlease provide a more detailed job description (at least 50 characters)
skills countMEDIUMRecommended 3+ skillsConsider adding more skills for better plan quality
jobDescription lengthMEDIUMRecommended 100+ charsA longer description produces more tailored interview questions

Data Quality Scores

ScoreCriteria
EXCELLENTNo CRITICAL/HIGH issues, job description 100+ chars, 3+ skills
GOODNo CRITICAL/HIGH issues but has MEDIUM warnings
ADEQUATEPasses minimum requirements (no CRITICAL, acceptable HIGH)
POORHas HIGH severity issues — triggers INFO_NEEDED
INVALIDHas CRITICAL missing fields — triggers INFO_NEEDED

Validation Logic

typescript
// Simplified DataValidationService logic
validateInterviewData(dto: CreateInterviewDto): ValidationResult {
  const issues: ValidationIssue[] = [];

  // CRITICAL checks
  if (!dto.candidateName?.trim()) {
    issues.push({ field: 'candidateName', severity: 'CRITICAL', ... });
  }
  if (!dto.candidateEmail || !isEmail(dto.candidateEmail)) {
    issues.push({ field: 'candidateEmail', severity: 'CRITICAL', ... });
  }
  if (!dto.position?.trim()) {
    issues.push({ field: 'position', severity: 'CRITICAL', ... });
  }

  // HIGH checks
  if (!dto.level) {
    issues.push({ field: 'level', severity: 'HIGH', ... });
  }
  if (!dto.skills?.length) {
    issues.push({ field: 'skills', severity: 'HIGH', ... });
  }
  if (!dto.jobDescription || dto.jobDescription.length < 50) {
    issues.push({ field: 'jobDescription', severity: 'HIGH', ... });
  }

  const needsHITL = issues.some(
    (i) => i.severity === 'CRITICAL' || i.severity === 'HIGH'
  );

  return {
    canProceed: !needsHITL,
    needsHITL,
    missingFields: issues,
    dataQuality: computeQuality(issues),
  };
}

INFO_NEEDED Response

When validation fails, the create endpoint returns a structured 201 (not an error) with the interview ID and the list of issues:

json
{
  "runId": "agno-run-uuid",
  "interviewId": "interview-uuid",
  "state": "INFO_NEEDED",
  "dataQuality": "POOR",
  "missingFields": [
    {
      "field": "jobDescription",
      "severity": "HIGH",
      "reason": "Job description too brief (< 50 chars)",
      "question": "Please provide a detailed job description"
    },
    {
      "field": "level",
      "severity": "HIGH",
      "reason": "Seniority level not specified",
      "question": "Please specify the seniority level (JUNIOR/MID/SENIOR/LEAD/PRINCIPAL)"
    }
  ]
}

Completing Missing Info

After receiving an INFO_NEEDED state, use the complete-info endpoint to supply the missing fields. The system re-validates — if all issues are resolved, it transitions to VALIDATING_SKILLS.

bash
curl -X PATCH http://localhost:3009/api/v1/a2a/interview/interview-uuid/complete-info \
  -H "Authorization: Bearer <jwt>" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "recruiter-uuid",
    "jobDescription": "We are looking for a senior engineer to lead our platform team...",
    "level": "SENIOR",
    "skills": ["TypeScript", "React", "Node.js", "PostgreSQL"]
  }'
Response 200
{
  "message": "Interview information completed. Skill validation starting.",
  "state": "VALIDATING_SKILLS"
}
Always provide all recommended fields (level, skills, 100+ char job description) in the initial request to achieve EXCELLENT data quality and skip the INFO_NEEDED state entirely.
Was this page helpful?