Advanced Usage
Manual Integration
Integration without heavy SDK automation assumptions
Manual Mode Principles
When you need explicit control over SDK behavior:
- Call SDK APIs at known UX milestones
- Control when to emit context-heavy events
- Keep data contracts strict and deterministic
- Verify behavior via backend activity
When to Use Manual Mode
- Complex navigation not suitable for auto-tracking
- Need explicit control over event timing
- Testing or debugging scenarios
- Custom lifecycle requirements
Minimal Manual Integration
// 1. Initialize (still required)
AI.init(
application = this,
apiKey = "your-api-key",
userId = "user-123",
policy = RuntimePolicy(
backendBaseUrl = "https://kycis.zynnex.in/v1",
triggerStartMode = TriggerStartMode.CONFIRM_UI,
passiveEvalEnabled = false // Disable passive evaluation
)
)
// 2. Skip attach() — no lifecycle tracking
// 3. Manual user set
AI.setUser(id = "user-123", phone = "9876543210", phoneMasked = true)Explicit Event Emission
Control exactly when events fire:
// Screen entry (manually controlled)
fun onScreenEnter(screenId: String) {
AI.setKycStep(screenId)
AI.reportScreenState(
screen = screenId,
metadata = mapOf("manual" to "true")
)
}
// Input tracking (throttled manually)
fun onInputChanged(componentId: String, value: String) {
// Your own debounce logic
debouncer.debounce("$componentId-input", 500) {
AI.reportComponentInput(
componentId = componentId,
hint = maskValue(value),
masked = true
)
}
}
// Validation (explicit call)
fun onValidationFailed(componentId: String, rule: String) {
AI.trackValidationFailure(
failureReasonCode = rule,
componentId = componentId
)
}Manual Trigger Evaluation
Skip automatic triggers, evaluate manually:
// Disable auto triggers
RuntimePolicy(
triggerSettings = TriggerSettings(
autoTriggerEnabled = false
)
)
// Manually evaluate when needed
fun checkShouldOfferHelp() {
// Your own logic
if (errorCount > 2 || timeOnScreen > 30) {
// Show your own UI
showHelpOffer()
}
}
// Direct assistant start
fun onUserAcceptsHelp() {
AI.startAssistant()
}Custom Lifecycle
When AI.attach() doesn't fit:
// Your own activity tracking
class MyLifecycleCallbacks : Application.ActivityLifecycleCallbacks {
override fun onActivityResumed(activity: Activity) {
// Custom screen detection
val screenId = detectScreen(activity)
AI.setKycStep(screenId)
}
}
// Register manually
application.registerActivityLifecycleCallbacks(MyLifecycleCallbacks())Verification Without Auto-Tracking
Since reduced tracking mode applies:
// Add your own analytics
AI.setStatusListener { status ->
analytics.track("kycis_manual", mapOf(
"code" to status.code.name
))
}
// Verify in backend
// Check /api/activity for all expected eventsTrade-offs
| Aspect | Auto (attach) | Manual |
|---|---|---|
| Setup | One line | Explicit everywhere |
| Screen tracking | Automatic | Manual calls |
| Passive signals | Available | Limited |
| Control | SDK decides | You decide |
| Debug complexity | Lower | Higher |
Recommended Hybrid
Keep some automation, add manual where needed:
// Enable attach for basic tracking
AI.attach(this)
// But override specific behaviors
RuntimePolicy(
passiveEvalEnabled = true, // Keep passive
triggerSettings = TriggerSettings(
autoTriggerEnabled = false // But control triggers
)
)
// Manual trigger with custom UI
fun onCustomStruggleDetected() {
showCustomHelpDialog()
}