@bluefly/openstandardagents 0.2.7 → 0.2.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.devfile.yaml +1 -1
- package/.env.example +1 -1
- package/.github/AGENTS.md +245 -0
- package/.github/agents/github-issue-triage.ossa.yaml +99 -0
- package/.github/agents/github-pr-triage.ossa.yaml +137 -0
- package/.github/workflows/issue-sync-to-gitlab.yml +138 -0
- package/.github/workflows/pr-triage-to-gitlab.yml +164 -0
- package/.version.json +2 -2
- package/.wiki-config.json +24 -0
- package/CHANGELOG.md +44 -18
- package/CODEOWNERS +75 -0
- package/CONTRIBUTING.md +103 -4
- package/README.md +178 -243
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/repositories/schema.repository.d.ts +6 -1
- package/dist/repositories/schema.repository.d.ts.map +1 -1
- package/dist/repositories/schema.repository.js +49 -27
- package/dist/repositories/schema.repository.js.map +1 -1
- package/dist/services/migration.service.d.ts +4 -3
- package/dist/services/migration.service.d.ts.map +1 -1
- package/dist/services/migration.service.js +11 -10
- package/dist/services/migration.service.js.map +1 -1
- package/dist/services/release-automation/release.service.js +1 -1
- package/dist/services/release-automation/release.service.js.map +1 -1
- package/dist/services/release-automation/schemas/release.schema.js +1 -1
- package/dist/services/release-automation/webhook.service.js +3 -3
- package/dist/services/release-automation/webhook.service.js.map +1 -1
- package/dist/services/runtime/claude/claude-adapter.d.ts +1 -1
- package/dist/services/runtime/claude/claude-adapter.d.ts.map +1 -1
- package/dist/services/runtime/claude/claude-adapter.js +2 -2
- package/dist/services/runtime/claude/claude-adapter.js.map +1 -1
- package/dist/spec/v0.2.8/CHANGELOG.md +401 -0
- package/dist/spec/v0.2.8/README.md +72 -0
- package/dist/spec/v0.2.8/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/dist/spec/v0.2.8/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
- package/dist/spec/v0.2.8/migrations/v0.2.6-to-v0.2.8.md +81 -0
- package/{spec/v0.2.6-dev/ossa-0.2.5.schema.json → dist/spec/v0.2.8/ossa-0.2.8.schema.json} +1509 -52
- package/dist/spec/v0.2.8/ossa-0.2.8.yaml +581 -0
- package/dist/spec/v0.2.9/a2a-protocol.md +1337 -0
- package/dist/spec/v0.2.9/agent.md +1946 -0
- package/dist/spec/v0.2.9/capabilities/index.yaml +25 -0
- package/dist/spec/v0.2.9/capabilities/memory.yaml +251 -0
- package/dist/spec/v0.2.9/capability-schema.md +576 -0
- package/dist/spec/v0.2.9/compliance-profiles.md +533 -0
- package/dist/spec/v0.2.9/conformance-testing.md +1527 -0
- package/dist/spec/v0.2.9/gitlab-duo-integration.md +621 -0
- package/dist/spec/v0.2.9/ossa-0.2.9.schema.json +3699 -0
- package/dist/spec/v0.2.9/runtime-semantics.md +464 -0
- package/dist/spec/v0.2.9/security-model.md +1245 -0
- package/dist/spec/v0.2.9/semantic-conventions.md +347 -0
- package/dist/spec/v0.2.9/types.ts +522 -0
- package/dist/types/index.d.ts +3 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/policy.d.ts +377 -0
- package/dist/types/policy.d.ts.map +1 -0
- package/dist/types/policy.js +84 -0
- package/dist/types/policy.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/version.d.ts +68 -0
- package/dist/utils/version.d.ts.map +1 -0
- package/dist/utils/version.js +156 -0
- package/dist/utils/version.js.map +1 -0
- package/docs/specs/policy-dsl.md +925 -0
- package/eslint-report.json +1 -0
- package/examples/adk-integration/code-review-workflow.yml +1 -1
- package/examples/adk-integration/customer-support.yml +1 -1
- package/examples/adk-integration/data-pipeline.yml +1 -1
- package/examples/advanced/reasoning-agent.yaml +136 -0
- package/examples/advanced/workflows/hybrid-model-strategy.yaml +1 -1
- package/examples/agent-manifests/critics/critic-agent.yaml +1 -1
- package/examples/agent-manifests/governors/governor-agent.yaml +1 -1
- package/examples/agent-manifests/integrators/integrator-agent.yaml +1 -1
- package/examples/agent-manifests/judges/judge-agent.yaml +1 -1
- package/examples/agent-manifests/monitors/monitor-agent.yaml +1 -1
- package/examples/agent-manifests/orchestrators/orchestrator-agent.yaml +1 -1
- package/examples/agent-manifests/sample-compliant-agent.yaml +1 -1
- package/examples/agent-manifests/workers/worker-agent.yaml +1 -1
- package/examples/agents-md/code-agent.ossa.json +100 -0
- package/examples/agents-md/monorepo-agent.ossa.yaml +180 -0
- package/examples/anthropic/claude-assistant.ossa.json +1 -1
- package/examples/autogen/multi-agent.ossa.json +1 -1
- package/examples/claude-code/code-reviewer.ossa.yaml +78 -0
- package/examples/claude-code/ossa-validator.ossa.yaml +80 -0
- package/examples/common_npm/agent-router.ossa.yaml +1 -0
- package/examples/common_npm/agent-router.v0.2.2.ossa.yaml +1 -1
- package/examples/crewai/research-team.ossa.json +1 -1
- package/examples/cursor/code-review-agent.ossa.json +1 -1
- package/examples/drupal/gitlab-ml-recommender.ossa.yaml +1 -0
- package/examples/drupal/gitlab-ml-recommender.v0.2.2.ossa.yaml +1 -1
- package/examples/extensions/agents-md-v1.yml +175 -0
- package/examples/extensions/drupal-v1.yml +1 -1
- package/examples/extensions/kagent-v1.yml +1 -1
- package/examples/getting-started/hello-world-complete.ossa.yaml +1 -1
- package/examples/integration-patterns/agent-to-agent-orchestration.ossa.yaml +4 -4
- package/examples/kagent/compliance-validator.ossa.yaml +1 -1
- package/examples/kagent/cost-optimizer.ossa.yaml +1 -1
- package/examples/kagent/documentation-agent.ossa.yaml +1 -1
- package/examples/kagent/k8s-troubleshooter-v1.ossa.yaml +1 -0
- package/examples/kagent/k8s-troubleshooter-v1.v0.2.2.ossa.yaml +1 -1
- package/examples/kagent/k8s-troubleshooter.ossa.yaml +1 -1
- package/examples/kagent/security-scanner.ossa.yaml +1 -1
- package/examples/langchain/chain-agent.ossa.json +1 -1
- package/examples/langflow/workflow-agent.ossa.json +1 -1
- package/examples/langgraph/state-machine-agent.ossa.json +1 -1
- package/examples/llamaindex/rag-agent.ossa.json +1 -1
- package/examples/migration-guides/from-langchain-to-ossa.yaml +4 -4
- package/examples/multi-agent/README.md +74 -0
- package/examples/multi-agent/conditional-router.ossa.yaml +42 -0
- package/examples/multi-agent/parallel-execution.ossa.yaml +54 -0
- package/examples/multi-agent/sequential-pipeline.ossa.yaml +45 -0
- package/examples/openai/basic-agent.ossa.yaml +1 -1
- package/examples/openai/multi-tool-agent.ossa.json +1 -1
- package/examples/openai/swarm-agent.ossa.json +1 -1
- package/examples/production/document-analyzer-openai.yml +1 -1
- package/examples/quickstart/support-agent.ossa.yaml +1 -1
- package/examples/spec-examples/audit-agent.yml +1 -1
- package/examples/spec-examples/chat-agent.yml +1 -1
- package/examples/spec-examples/compliance-agent.yml +1 -1
- package/examples/spec-examples/monitoring-agent.yml +1 -1
- package/examples/spec-examples/workflow-agent.yml +1 -1
- package/examples/templates/ossa-compliance.yaml +1 -1
- package/examples/vercel/edge-agent.ossa.json +1 -1
- package/gl-code-quality-report.json +62 -0
- package/llms-ctx-full.txt +39 -0
- package/llms-ctx.txt +39 -0
- package/llms.txt +47 -0
- package/package.json +6 -3
- package/scripts/README.md +25 -0
- package/scripts/compliance-audit.ts +796 -0
- package/scripts/eslint-to-codequality.cjs +34 -0
- package/scripts/generate-agents-catalog.ts +2 -1
- package/scripts/generate-api-docs.ts +2 -1
- package/scripts/generate-examples-docs.ts +2 -1
- package/scripts/generate-llms-ctx.sh +17 -0
- package/scripts/generate-schema-docs.ts +31 -10
- package/scripts/sync-version.js +4 -12
- package/scripts/validate-schema.ts +2 -1
- package/spec/v0.2.8/CHANGELOG.md +401 -0
- package/spec/v0.2.8/README.md +72 -0
- package/spec/v0.2.8/migrations/v0.2.3-to-v0.2.4.md +599 -0
- package/spec/v0.2.8/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
- package/spec/v0.2.8/migrations/v0.2.6-to-v0.2.8.md +81 -0
- package/spec/{v0.2.6-dev/ossa-0.2.6-dev.schema.json → v0.2.8/ossa-0.2.8.schema.json} +1509 -52
- package/spec/v0.2.8/ossa-0.2.8.yaml +581 -0
- package/spec/v0.2.9/a2a-protocol.md +1337 -0
- package/spec/v0.2.9/agent.md +1946 -0
- package/spec/v0.2.9/capabilities/index.yaml +25 -0
- package/spec/v0.2.9/capabilities/memory.yaml +251 -0
- package/spec/v0.2.9/capability-schema.md +576 -0
- package/spec/v0.2.9/compliance-profiles.md +533 -0
- package/spec/v0.2.9/conformance-testing.md +1527 -0
- package/spec/v0.2.9/gitlab-duo-integration.md +621 -0
- package/spec/v0.2.9/ossa-0.2.9.schema.json +3699 -0
- package/spec/v0.2.9/runtime-semantics.md +464 -0
- package/spec/v0.2.9/security-model.md +1245 -0
- package/spec/v0.2.9/semantic-conventions.md +347 -0
- package/spec/v0.2.9/types.ts +522 -0
- package/test-results/junit.xml +337 -0
- package/.github/workflows/pr-comment.yml +0 -33
- package/bin/validate-ossa-0.2.5-RC.ts +0 -244
- package/dist/spec/v0.2.6-dev/ossa-0.2.5.schema.json +0 -1696
- package/dist/spec/v0.2.6-dev/ossa-0.2.6-dev.schema.json +0 -1696
- package/scripts/lib/exec.ts +0 -37
- package/scripts/lib/file-ops.ts +0 -58
- package/scripts/lib/version.ts +0 -83
- package/website/.lighthouserc.ts +0 -24
- package/website/.prettierrc +0 -10
- package/website/DESIGN_SYSTEM_IMPLEMENTATION.md +0 -445
- package/website/Dockerfile +0 -30
- package/website/app/about/page.tsx +0 -304
- package/website/app/blog/[slug]/page.tsx +0 -208
- package/website/app/blog/page.tsx +0 -249
- package/website/app/design-guide/page.tsx +0 -511
- package/website/app/docs/[[...slug]]/page.tsx +0 -847
- package/website/app/docs/core-concepts/project-structure/page.tsx +0 -349
- package/website/app/ecosystem/page.tsx +0 -410
- package/website/app/examples/page.tsx +0 -133
- package/website/app/globals.scss +0 -370
- package/website/app/layout.tsx +0 -106
- package/website/app/license/page.tsx +0 -183
- package/website/app/not-found.tsx +0 -18
- package/website/app/page.tsx +0 -686
- package/website/app/page.tsx.bak +0 -679
- package/website/app/page.tsx.bak2 +0 -649
- package/website/app/playground/page.tsx +0 -487
- package/website/app/robots.ts +0 -19
- package/website/app/rss.xml/route.ts +0 -74
- package/website/app/schema/page.tsx +0 -1001
- package/website/app/sitemap.ts +0 -56
- package/website/app/specification/page.tsx +0 -287
- package/website/components/InstallCommand.tsx +0 -96
- package/website/components/Logo.tsx +0 -97
- package/website/components/StructuredData.tsx +0 -65
- package/website/components/docs/DocsSearch.tsx +0 -104
- package/website/components/docs/DocsSidebar.tsx +0 -155
- package/website/components/docs/MarkdownContent.tsx +0 -401
- package/website/components/docs/VersionSelector.tsx +0 -105
- package/website/components/examples/ExamplesViewer.tsx +0 -293
- package/website/components/layout/Footer.tsx +0 -116
- package/website/components/layout/Header.tsx +0 -172
- package/website/components/schema/SchemaComponentsAccordion.tsx +0 -84
- package/website/components/schema/SchemaExplorer.tsx +0 -213
- package/website/components/ui/Badge.tsx +0 -82
- package/website/components/ui/Button.tsx +0 -116
- package/website/components/ui/Card.tsx +0 -167
- package/website/components/ui/Checkbox.tsx +0 -141
- package/website/components/ui/Input.tsx +0 -169
- package/website/components/ui/Radio.tsx +0 -141
- package/website/components/ui/Select.tsx +0 -182
- package/website/components/ui/Tag.tsx +0 -158
- package/website/components/ui/Textarea.tsx +0 -195
- package/website/components/ui/index.ts +0 -11
- package/website/content/blog/OpenAPI-AI-Agents-Standard.md +0 -285
- package/website/content/blog/Why-Formal-Standards-Matter-Now.md +0 -198
- package/website/content/blog/gitlab-kubernetes-agent-ecosystem.md +0 -286
- package/website/content/blog/introducing-ossa-framework.md +0 -328
- package/website/content/blog/ossa-production-results.md +0 -279
- package/website/content/blog/welcome-to-ossa.md +0 -43
- package/website/content/blog/why-ai-agents-need-open-standard.md +0 -98
- package/website/content/docs/00-home.md +0 -153
- package/website/content/docs/adapters/openai-adapter.md +0 -693
- package/website/content/docs/agents/catalog.md +0 -28
- package/website/content/docs/aiflow-framework-integration-with-ossa.md +0 -107
- package/website/content/docs/api-reference/index.md +0 -38
- package/website/content/docs/api-reference/ossa-core-api.md +0 -634
- package/website/content/docs/api-reference/ossa-registry-api.md +0 -515
- package/website/content/docs/api-reference/unified-agent-gateway.md +0 -599
- package/website/content/docs/architecture/execution-flow.md +0 -335
- package/website/content/docs/architecture/multi-agent-systems.md +0 -737
- package/website/content/docs/architecture/overview.md +0 -121
- package/website/content/docs/architecture/stack-integration.md +0 -461
- package/website/content/docs/changelog.md +0 -246
- package/website/content/docs/cli-reference/index.md +0 -111
- package/website/content/docs/cli-reference/ossa-agents.md +0 -70
- package/website/content/docs/cli-reference/ossa-export.md +0 -56
- package/website/content/docs/cli-reference/ossa-generate.md +0 -66
- package/website/content/docs/cli-reference/ossa-gitlab-agent.md +0 -57
- package/website/content/docs/cli-reference/ossa-import.md +0 -56
- package/website/content/docs/cli-reference/ossa-init.md +0 -57
- package/website/content/docs/cli-reference/ossa-migrate.md +0 -62
- package/website/content/docs/cli-reference/ossa-run.md +0 -66
- package/website/content/docs/cli-reference/ossa-schema.md +0 -57
- package/website/content/docs/cli-reference/ossa-setup.md +0 -57
- package/website/content/docs/cli-reference/ossa-validate.md +0 -66
- package/website/content/docs/configuration/index.md +0 -97
- package/website/content/docs/contributing.md +0 -599
- package/website/content/docs/deployment/github-mirroring.md +0 -924
- package/website/content/docs/documentation.md +0 -100
- package/website/content/docs/ecosystem/framework-support.md +0 -1361
- package/website/content/docs/ecosystem/overview.md +0 -366
- package/website/content/docs/errors/index.md +0 -10
- package/website/content/docs/examples/aiflow-framework-integration-with-ossa.md +0 -107
- package/website/content/docs/examples/catalog.md +0 -300
- package/website/content/docs/for-audiences/students-researchers.md +0 -122
- package/website/content/docs/getting-started/index.md +0 -92
- package/website/content/docs/getting-started/installation.md +0 -155
- package/website/content/docs/getting-started/running-agents.md +0 -309
- package/website/content/docs/getting-started.md +0 -91
- package/website/content/docs/integrations/aiflow.md +0 -104
- package/website/content/docs/integrations/drupal.md +0 -105
- package/website/content/docs/migration-guides/agent-schema-comparison.md +0 -232
- package/website/content/docs/migration-guides/anthropic-mcp-to-ossa.md +0 -1750
- package/website/content/docs/migration-guides/crewai-to-ossa.md +0 -274
- package/website/content/docs/migration-guides/drupal-eca-to-ossa.md +0 -2017
- package/website/content/docs/migration-guides/general-agent-schema.yml +0 -247
- package/website/content/docs/migration-guides/index.md +0 -133
- package/website/content/docs/migration-guides/langchain-to-ossa.md +0 -1714
- package/website/content/docs/migration-guides/langflow-to-ossa.md +0 -2075
- package/website/content/docs/migration-guides/migration-manifest.json +0 -64
- package/website/content/docs/migration-guides/openai-to-ossa.md +0 -1202
- package/website/content/docs/openapi-extensions/examples.md +0 -550
- package/website/content/docs/openapi-extensions/index.md +0 -551
- package/website/content/docs/openapi-extensions/operation-extensions.md +0 -457
- package/website/content/docs/openapi-extensions/root-extensions.md +0 -410
- package/website/content/docs/ossa-compliant-badge.md +0 -251
- package/website/content/docs/pre-release/index.md +0 -175
- package/website/content/docs/quick-reference.md +0 -17
- package/website/content/docs/readme.md +0 -35
- package/website/content/docs/releases/v0.2.6.md +0 -99
- package/website/content/docs/schema-reference/agent-capabilities.md +0 -50
- package/website/content/docs/schema-reference/agent-id.md +0 -52
- package/website/content/docs/schema-reference/agent-name.md +0 -50
- package/website/content/docs/schema-reference/agent-role.md +0 -54
- package/website/content/docs/schema-reference/agent-spec.md +0 -406
- package/website/content/docs/schema-reference/agent-version.md +0 -50
- package/website/content/docs/schema-reference/autonomy.md +0 -568
- package/website/content/docs/schema-reference/constraints.md +0 -543
- package/website/content/docs/schema-reference/index.md +0 -45
- package/website/content/docs/schema-reference/llm-config.md +0 -445
- package/website/content/docs/schema-reference/observability.md +0 -654
- package/website/content/docs/schema-reference/ossa-manifest.md +0 -309
- package/website/content/docs/schema-reference/taxonomy.md +0 -509
- package/website/content/docs/schema-reference/tools.md +0 -628
- package/website/content/docs/templates/blog-post.md +0 -43
- package/website/content/docs/types-reference/index.md +0 -105
- package/website/content/docs/use-cases/00-index.md +0 -395
- package/website/content/docs/use-cases/cicd-code-review.md +0 -1236
- package/website/content/docs/use-cases/customer-support.md +0 -1234
- package/website/content/docs/use-cases/enterprise-compliance.md +0 -1208
- package/website/content/docs/use-cases/research-multi-agent.md +0 -1161
- package/website/content/docs/versioning.md +0 -288
- package/website/dev.sh +0 -53
- package/website/docker-compose.dev.yml +0 -36
- package/website/lib/version.ts +0 -35
- package/website/lib/versions.json +0 -103
- package/website/next.config.ts +0 -18
- package/website/nginx.conf +0 -32
- package/website/package-lock.json +0 -9679
- package/website/package.json +0 -59
- package/website/postcss.config.mjs +0 -9
- package/website/scripts/fetch-versions.js +0 -166
- package/website/scripts/generate-examples-index.js +0 -163
- package/website/scripts/merge-docs-to-wiki.ts +0 -207
- package/website/scripts/sync-version.js +0 -72
- package/website/scripts/sync-wiki.ts +0 -322
- package/website/scripts/upload-wiki.ts +0 -199
- package/website/styles/_spacing.scss +0 -453
- package/website/styles/_tokens.scss +0 -245
- package/website/styles/_typography.scss +0 -361
- package/website/styles/_variables.scss +0 -287
- package/website/tailwind.config.ts +0 -170
|
@@ -1,1234 +0,0 @@
|
|
|
1
|
-
# Customer Support Ticket Triage Agent
|
|
2
|
-
|
|
3
|
-
## Problem Statement
|
|
4
|
-
|
|
5
|
-
Customer support teams face overwhelming ticket volumes:
|
|
6
|
-
- **Response time bottlenecks**: Average first response time 4-8 hours
|
|
7
|
-
- **Misrouted tickets**: 30% of tickets assigned to wrong team/person
|
|
8
|
-
- **Inconsistent prioritization**: Critical issues buried under low-priority requests
|
|
9
|
-
- **Knowledge gaps**: Support agents spend 40% of time searching for answers
|
|
10
|
-
- **Escalation delays**: High-value customers wait in same queue as free-tier users
|
|
11
|
-
- **No 24/7 coverage**: After-hours tickets pile up until next business day
|
|
12
|
-
|
|
13
|
-
**Solution**: An OSSA-powered support agent that automatically triages tickets, assigns priority and routing, surfaces relevant knowledge base articles, suggests responses, and escalates critical issues to human agents—reducing response time from hours to seconds.
|
|
14
|
-
|
|
15
|
-
## Architecture Overview
|
|
16
|
-
|
|
17
|
-
```mermaid
|
|
18
|
-
graph TB
|
|
19
|
-
subgraph "Input Channels"
|
|
20
|
-
Email[Email Support]
|
|
21
|
-
Chat[Live Chat]
|
|
22
|
-
Form[Web Form]
|
|
23
|
-
API[API Tickets]
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
subgraph "Triage Agent"
|
|
27
|
-
Classifier[Ticket Classifier]
|
|
28
|
-
Priority[Priority Scorer]
|
|
29
|
-
Router[Routing Engine]
|
|
30
|
-
KB[Knowledge Base Search]
|
|
31
|
-
Sentiment[Sentiment Analysis]
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
subgraph "AI Processing"
|
|
35
|
-
LLM[GPT-4/Claude]
|
|
36
|
-
Embeddings[Vector Embeddings]
|
|
37
|
-
Intent[Intent Detection]
|
|
38
|
-
Entity[Entity Extraction]
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
subgraph "Actions"
|
|
42
|
-
AutoReply[Auto-Reply]
|
|
43
|
-
Escalate[Escalate to Human]
|
|
44
|
-
Assign[Assign to Team]
|
|
45
|
-
Suggest[Suggest Response]
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
subgraph "Integrations"
|
|
49
|
-
Zendesk[Zendesk]
|
|
50
|
-
Intercom[Intercom]
|
|
51
|
-
Slack[Slack Alerts]
|
|
52
|
-
CRM[CRM Sync]
|
|
53
|
-
end
|
|
54
|
-
|
|
55
|
-
Email --> Classifier
|
|
56
|
-
Chat --> Classifier
|
|
57
|
-
Form --> Classifier
|
|
58
|
-
API --> Classifier
|
|
59
|
-
|
|
60
|
-
Classifier --> LLM
|
|
61
|
-
Classifier --> Priority
|
|
62
|
-
Classifier --> Router
|
|
63
|
-
Classifier --> KB
|
|
64
|
-
|
|
65
|
-
LLM --> Intent
|
|
66
|
-
LLM --> Entity
|
|
67
|
-
LLM --> Sentiment
|
|
68
|
-
|
|
69
|
-
Priority --> AutoReply
|
|
70
|
-
Priority --> Escalate
|
|
71
|
-
Router --> Assign
|
|
72
|
-
KB --> Suggest
|
|
73
|
-
|
|
74
|
-
AutoReply --> Zendesk
|
|
75
|
-
Escalate --> Slack
|
|
76
|
-
Assign --> Zendesk
|
|
77
|
-
Suggest --> Zendesk
|
|
78
|
-
Assign --> CRM
|
|
79
|
-
|
|
80
|
-
style Classifier fill:#e1f5ff
|
|
81
|
-
style LLM fill:#ffe1f5
|
|
82
|
-
style Escalate fill:#ffe1e1
|
|
83
|
-
style AutoReply fill:#e1ffe1
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
## OSSA Manifest
|
|
87
|
-
|
|
88
|
-
```yaml
|
|
89
|
-
apiVersion: ossa/v0.2.x
|
|
90
|
-
kind: Agent
|
|
91
|
-
metadata:
|
|
92
|
-
name: support-triage-agent
|
|
93
|
-
namespace: customer-support
|
|
94
|
-
labels:
|
|
95
|
-
app: support
|
|
96
|
-
tier: customer-facing
|
|
97
|
-
criticality: high
|
|
98
|
-
annotations:
|
|
99
|
-
support.ossa.io/sla-critical: "15m"
|
|
100
|
-
support.ossa.io/sla-high: "2h"
|
|
101
|
-
support.ossa.io/sla-normal: "24h"
|
|
102
|
-
support.ossa.io/auto-reply-enabled: "true"
|
|
103
|
-
cost.ossa.io/budget-monthly: "500.00"
|
|
104
|
-
|
|
105
|
-
spec:
|
|
106
|
-
type: worker
|
|
107
|
-
description: |
|
|
108
|
-
Intelligent customer support ticket triage agent.
|
|
109
|
-
Automatically classifies, prioritizes, routes, and responds to
|
|
110
|
-
customer support tickets with knowledge base integration.
|
|
111
|
-
|
|
112
|
-
runtime:
|
|
113
|
-
type: docker
|
|
114
|
-
image: registry.example.com/agents/support-triage:2.5.0
|
|
115
|
-
command: ["/app/triage-agent"]
|
|
116
|
-
args:
|
|
117
|
-
- "--mode=realtime"
|
|
118
|
-
- "--auto-reply=smart"
|
|
119
|
-
- "--escalation-threshold=0.85"
|
|
120
|
-
resources:
|
|
121
|
-
limits:
|
|
122
|
-
cpu: "2000m"
|
|
123
|
-
memory: "4Gi"
|
|
124
|
-
requests:
|
|
125
|
-
cpu: "500m"
|
|
126
|
-
memory: "1Gi"
|
|
127
|
-
env:
|
|
128
|
-
- name: LOG_LEVEL
|
|
129
|
-
value: "info"
|
|
130
|
-
- name: AI_MODEL
|
|
131
|
-
value: "gpt-4-turbo-preview"
|
|
132
|
-
- name: KNOWLEDGE_BASE_PROVIDER
|
|
133
|
-
value: "pinecone"
|
|
134
|
-
- name: ENABLE_AUTO_REPLY
|
|
135
|
-
value: "true"
|
|
136
|
-
- name: ENABLE_SENTIMENT_ANALYSIS
|
|
137
|
-
value: "true"
|
|
138
|
-
- name: MAX_AUTO_REPLY_CONFIDENCE
|
|
139
|
-
value: "0.95"
|
|
140
|
-
|
|
141
|
-
capabilities:
|
|
142
|
-
- name: triage_ticket
|
|
143
|
-
description: |
|
|
144
|
-
Comprehensive ticket triage including classification,
|
|
145
|
-
prioritization, routing, knowledge base search, and
|
|
146
|
-
response suggestion.
|
|
147
|
-
input_schema:
|
|
148
|
-
type: object
|
|
149
|
-
required: [ticket_id, subject, body, customer_id]
|
|
150
|
-
properties:
|
|
151
|
-
ticket_id:
|
|
152
|
-
type: string
|
|
153
|
-
description: "Unique ticket identifier"
|
|
154
|
-
subject:
|
|
155
|
-
type: string
|
|
156
|
-
description: "Ticket subject line"
|
|
157
|
-
body:
|
|
158
|
-
type: string
|
|
159
|
-
description: "Full ticket content"
|
|
160
|
-
customer_id:
|
|
161
|
-
type: string
|
|
162
|
-
description: "Customer identifier"
|
|
163
|
-
customer_tier:
|
|
164
|
-
type: string
|
|
165
|
-
enum: [free, basic, pro, enterprise]
|
|
166
|
-
default: basic
|
|
167
|
-
channel:
|
|
168
|
-
type: string
|
|
169
|
-
enum: [email, chat, form, api, phone]
|
|
170
|
-
default: email
|
|
171
|
-
attachments:
|
|
172
|
-
type: array
|
|
173
|
-
items:
|
|
174
|
-
type: object
|
|
175
|
-
properties:
|
|
176
|
-
filename: {type: string}
|
|
177
|
-
url: {type: string}
|
|
178
|
-
content_type: {type: string}
|
|
179
|
-
metadata:
|
|
180
|
-
type: object
|
|
181
|
-
description: "Additional ticket metadata"
|
|
182
|
-
output_schema:
|
|
183
|
-
type: object
|
|
184
|
-
required: [ticket_id, category, priority, routing, action]
|
|
185
|
-
properties:
|
|
186
|
-
ticket_id:
|
|
187
|
-
type: string
|
|
188
|
-
category:
|
|
189
|
-
type: string
|
|
190
|
-
enum: [
|
|
191
|
-
billing,
|
|
192
|
-
technical,
|
|
193
|
-
feature_request,
|
|
194
|
-
bug_report,
|
|
195
|
-
account_management,
|
|
196
|
-
general_inquiry,
|
|
197
|
-
complaint,
|
|
198
|
-
feedback
|
|
199
|
-
]
|
|
200
|
-
subcategory:
|
|
201
|
-
type: string
|
|
202
|
-
priority:
|
|
203
|
-
type: string
|
|
204
|
-
enum: [critical, high, normal, low]
|
|
205
|
-
priority_score:
|
|
206
|
-
type: number
|
|
207
|
-
minimum: 0
|
|
208
|
-
maximum: 100
|
|
209
|
-
routing:
|
|
210
|
-
type: object
|
|
211
|
-
required: [team, suggested_agent]
|
|
212
|
-
properties:
|
|
213
|
-
team:
|
|
214
|
-
type: string
|
|
215
|
-
enum: [billing, engineering, sales, success, general]
|
|
216
|
-
suggested_agent:
|
|
217
|
-
type: string
|
|
218
|
-
skills_required:
|
|
219
|
-
type: array
|
|
220
|
-
items: {type: string}
|
|
221
|
-
sentiment:
|
|
222
|
-
type: object
|
|
223
|
-
properties:
|
|
224
|
-
score:
|
|
225
|
-
type: number
|
|
226
|
-
minimum: -1
|
|
227
|
-
maximum: 1
|
|
228
|
-
label:
|
|
229
|
-
type: string
|
|
230
|
-
enum: [very_negative, negative, neutral, positive, very_positive]
|
|
231
|
-
angry:
|
|
232
|
-
type: boolean
|
|
233
|
-
frustrated:
|
|
234
|
-
type: boolean
|
|
235
|
-
intent:
|
|
236
|
-
type: array
|
|
237
|
-
items:
|
|
238
|
-
type: string
|
|
239
|
-
description: "Detected customer intents"
|
|
240
|
-
entities:
|
|
241
|
-
type: object
|
|
242
|
-
description: "Extracted entities (product names, error codes, etc.)"
|
|
243
|
-
knowledge_base_matches:
|
|
244
|
-
type: array
|
|
245
|
-
items:
|
|
246
|
-
type: object
|
|
247
|
-
properties:
|
|
248
|
-
article_id: {type: string}
|
|
249
|
-
title: {type: string}
|
|
250
|
-
url: {type: string}
|
|
251
|
-
relevance_score: {type: number}
|
|
252
|
-
snippet: {type: string}
|
|
253
|
-
suggested_response:
|
|
254
|
-
type: string
|
|
255
|
-
description: "AI-generated response suggestion"
|
|
256
|
-
confidence:
|
|
257
|
-
type: number
|
|
258
|
-
minimum: 0
|
|
259
|
-
maximum: 1
|
|
260
|
-
description: "Confidence in triage decisions"
|
|
261
|
-
action:
|
|
262
|
-
type: string
|
|
263
|
-
enum: [auto_reply, escalate, assign, pending_info]
|
|
264
|
-
escalation_reason:
|
|
265
|
-
type: string
|
|
266
|
-
sla_deadline:
|
|
267
|
-
type: string
|
|
268
|
-
format: date-time
|
|
269
|
-
tags:
|
|
270
|
-
type: array
|
|
271
|
-
items: {type: string}
|
|
272
|
-
timestamp:
|
|
273
|
-
type: string
|
|
274
|
-
format: date-time
|
|
275
|
-
|
|
276
|
-
- name: search_knowledge_base
|
|
277
|
-
description: |
|
|
278
|
-
Search knowledge base for relevant articles using
|
|
279
|
-
semantic search with vector embeddings.
|
|
280
|
-
input_schema:
|
|
281
|
-
type: object
|
|
282
|
-
required: [query]
|
|
283
|
-
properties:
|
|
284
|
-
query:
|
|
285
|
-
type: string
|
|
286
|
-
description: "Search query"
|
|
287
|
-
category:
|
|
288
|
-
type: string
|
|
289
|
-
description: "Filter by category"
|
|
290
|
-
limit:
|
|
291
|
-
type: integer
|
|
292
|
-
default: 5
|
|
293
|
-
minimum: 1
|
|
294
|
-
maximum: 20
|
|
295
|
-
output_schema:
|
|
296
|
-
type: object
|
|
297
|
-
properties:
|
|
298
|
-
results:
|
|
299
|
-
type: array
|
|
300
|
-
items:
|
|
301
|
-
type: object
|
|
302
|
-
required: [id, title, content, score]
|
|
303
|
-
properties:
|
|
304
|
-
id: {type: string}
|
|
305
|
-
title: {type: string}
|
|
306
|
-
content: {type: string}
|
|
307
|
-
url: {type: string}
|
|
308
|
-
category: {type: string}
|
|
309
|
-
score: {type: number}
|
|
310
|
-
last_updated: {type: string, format: date-time}
|
|
311
|
-
|
|
312
|
-
- name: generate_response
|
|
313
|
-
description: |
|
|
314
|
-
Generate contextual response suggestion based on
|
|
315
|
-
ticket content and knowledge base.
|
|
316
|
-
input_schema:
|
|
317
|
-
type: object
|
|
318
|
-
required: [ticket_content, knowledge_articles]
|
|
319
|
-
properties:
|
|
320
|
-
ticket_content:
|
|
321
|
-
type: string
|
|
322
|
-
knowledge_articles:
|
|
323
|
-
type: array
|
|
324
|
-
items:
|
|
325
|
-
type: object
|
|
326
|
-
customer_history:
|
|
327
|
-
type: array
|
|
328
|
-
items:
|
|
329
|
-
type: object
|
|
330
|
-
tone:
|
|
331
|
-
type: string
|
|
332
|
-
enum: [professional, friendly, empathetic, concise]
|
|
333
|
-
default: professional
|
|
334
|
-
output_schema:
|
|
335
|
-
type: object
|
|
336
|
-
properties:
|
|
337
|
-
response:
|
|
338
|
-
type: string
|
|
339
|
-
confidence:
|
|
340
|
-
type: number
|
|
341
|
-
reasoning:
|
|
342
|
-
type: string
|
|
343
|
-
follow_up_actions:
|
|
344
|
-
type: array
|
|
345
|
-
items: {type: string}
|
|
346
|
-
|
|
347
|
-
- name: escalate_ticket
|
|
348
|
-
description: |
|
|
349
|
-
Escalate ticket to human agent with context and reasoning.
|
|
350
|
-
input_schema:
|
|
351
|
-
type: object
|
|
352
|
-
required: [ticket_id, reason]
|
|
353
|
-
properties:
|
|
354
|
-
ticket_id:
|
|
355
|
-
type: string
|
|
356
|
-
reason:
|
|
357
|
-
type: string
|
|
358
|
-
enum: [
|
|
359
|
-
high_value_customer,
|
|
360
|
-
angry_customer,
|
|
361
|
-
complex_issue,
|
|
362
|
-
low_confidence,
|
|
363
|
-
legal_concern,
|
|
364
|
-
security_incident
|
|
365
|
-
]
|
|
366
|
-
urgency:
|
|
367
|
-
type: string
|
|
368
|
-
enum: [immediate, high, normal]
|
|
369
|
-
suggested_team:
|
|
370
|
-
type: string
|
|
371
|
-
context:
|
|
372
|
-
type: string
|
|
373
|
-
output_schema:
|
|
374
|
-
type: object
|
|
375
|
-
properties:
|
|
376
|
-
escalated:
|
|
377
|
-
type: boolean
|
|
378
|
-
assigned_to:
|
|
379
|
-
type: string
|
|
380
|
-
notification_sent:
|
|
381
|
-
type: boolean
|
|
382
|
-
escalation_id:
|
|
383
|
-
type: string
|
|
384
|
-
|
|
385
|
-
- name: analyze_sentiment
|
|
386
|
-
description: |
|
|
387
|
-
Analyze customer sentiment and emotional tone.
|
|
388
|
-
input_schema:
|
|
389
|
-
type: object
|
|
390
|
-
required: [text]
|
|
391
|
-
properties:
|
|
392
|
-
text:
|
|
393
|
-
type: string
|
|
394
|
-
output_schema:
|
|
395
|
-
type: object
|
|
396
|
-
properties:
|
|
397
|
-
sentiment_score:
|
|
398
|
-
type: number
|
|
399
|
-
minimum: -1
|
|
400
|
-
maximum: 1
|
|
401
|
-
sentiment_label:
|
|
402
|
-
type: string
|
|
403
|
-
emotions:
|
|
404
|
-
type: object
|
|
405
|
-
properties:
|
|
406
|
-
angry: {type: number}
|
|
407
|
-
frustrated: {type: number}
|
|
408
|
-
confused: {type: number}
|
|
409
|
-
satisfied: {type: number}
|
|
410
|
-
urgency_indicators:
|
|
411
|
-
type: array
|
|
412
|
-
items: {type: string}
|
|
413
|
-
|
|
414
|
-
policies:
|
|
415
|
-
sla:
|
|
416
|
-
critical: 15 # minutes
|
|
417
|
-
high: 120 # minutes
|
|
418
|
-
normal: 1440 # minutes (24 hours)
|
|
419
|
-
low: 2880 # minutes (48 hours)
|
|
420
|
-
|
|
421
|
-
auto_reply:
|
|
422
|
-
enabled: true
|
|
423
|
-
conditions:
|
|
424
|
-
min_confidence: 0.95
|
|
425
|
-
max_complexity: low
|
|
426
|
-
exclude_categories: [complaint, legal, security]
|
|
427
|
-
exclude_tiers: [enterprise]
|
|
428
|
-
exclude_angry_customers: true
|
|
429
|
-
approval_required: false
|
|
430
|
-
human_review_sample_rate: 0.10 # Review 10% of auto-replies
|
|
431
|
-
|
|
432
|
-
escalation:
|
|
433
|
-
automatic_triggers:
|
|
434
|
-
- condition: customer_tier == "enterprise"
|
|
435
|
-
action: escalate_immediately
|
|
436
|
-
- condition: sentiment_score < -0.7
|
|
437
|
-
action: escalate_to_senior
|
|
438
|
-
- condition: contains_keywords("refund", "cancel", "lawyer")
|
|
439
|
-
action: escalate_to_manager
|
|
440
|
-
- condition: confidence < 0.6
|
|
441
|
-
action: assign_to_human
|
|
442
|
-
notification_channels:
|
|
443
|
-
critical: [slack, email, sms]
|
|
444
|
-
high: [slack, email]
|
|
445
|
-
normal: [email]
|
|
446
|
-
|
|
447
|
-
routing:
|
|
448
|
-
teams:
|
|
449
|
-
billing:
|
|
450
|
-
keywords: [payment, invoice, refund, subscription, billing]
|
|
451
|
-
skills: [payments, accounting]
|
|
452
|
-
engineering:
|
|
453
|
-
keywords: [bug, error, crash, not working, technical]
|
|
454
|
-
skills: [debugging, api, integration]
|
|
455
|
-
sales:
|
|
456
|
-
keywords: [upgrade, pricing, demo, trial, enterprise]
|
|
457
|
-
skills: [sales, product_knowledge]
|
|
458
|
-
success:
|
|
459
|
-
keywords: [onboarding, training, best practices]
|
|
460
|
-
skills: [customer_success, training]
|
|
461
|
-
|
|
462
|
-
cost_management:
|
|
463
|
-
budget:
|
|
464
|
-
monthly_limit_usd: 500.00
|
|
465
|
-
per_ticket_limit_usd: 0.50
|
|
466
|
-
alert_threshold: 0.85
|
|
467
|
-
optimization:
|
|
468
|
-
cache_kb_searches: true
|
|
469
|
-
batch_processing: true
|
|
470
|
-
use_cheaper_model_when_possible: true
|
|
471
|
-
|
|
472
|
-
integration:
|
|
473
|
-
protocol: webhook
|
|
474
|
-
api_version: v1
|
|
475
|
-
|
|
476
|
-
webhooks:
|
|
477
|
-
zendesk:
|
|
478
|
-
url: https://support-triage.example.com/webhooks/zendesk
|
|
479
|
-
events:
|
|
480
|
-
- ticket.created
|
|
481
|
-
- ticket.updated
|
|
482
|
-
secret_env: ZENDESK_WEBHOOK_SECRET
|
|
483
|
-
|
|
484
|
-
intercom:
|
|
485
|
-
url: https://support-triage.example.com/webhooks/intercom
|
|
486
|
-
events:
|
|
487
|
-
- conversation.created
|
|
488
|
-
- conversation.admin.replied
|
|
489
|
-
secret_env: INTERCOM_WEBHOOK_SECRET
|
|
490
|
-
|
|
491
|
-
apis:
|
|
492
|
-
zendesk:
|
|
493
|
-
base_url: https://example.zendesk.com/api/v2
|
|
494
|
-
auth:
|
|
495
|
-
type: bearer
|
|
496
|
-
token_env: ZENDESK_API_TOKEN
|
|
497
|
-
|
|
498
|
-
intercom:
|
|
499
|
-
base_url: https://api.intercom.io
|
|
500
|
-
auth:
|
|
501
|
-
type: bearer
|
|
502
|
-
token_env: INTERCOM_ACCESS_TOKEN
|
|
503
|
-
|
|
504
|
-
slack:
|
|
505
|
-
base_url: https://slack.com/api
|
|
506
|
-
auth:
|
|
507
|
-
type: bearer
|
|
508
|
-
token_env: SLACK_BOT_TOKEN
|
|
509
|
-
|
|
510
|
-
endpoints:
|
|
511
|
-
triage:
|
|
512
|
-
path: /v1/triage/ticket
|
|
513
|
-
method: POST
|
|
514
|
-
rate_limit: 1000/hour
|
|
515
|
-
|
|
516
|
-
search_kb:
|
|
517
|
-
path: /v1/knowledge-base/search
|
|
518
|
-
method: GET
|
|
519
|
-
rate_limit: 5000/hour
|
|
520
|
-
|
|
521
|
-
escalate:
|
|
522
|
-
path: /v1/escalate
|
|
523
|
-
method: POST
|
|
524
|
-
rate_limit: 500/hour
|
|
525
|
-
|
|
526
|
-
monitoring:
|
|
527
|
-
health_check:
|
|
528
|
-
endpoint: http://localhost:8080/health
|
|
529
|
-
interval_seconds: 30
|
|
530
|
-
|
|
531
|
-
metrics:
|
|
532
|
-
enabled: true
|
|
533
|
-
exporter: prometheus
|
|
534
|
-
custom_metrics:
|
|
535
|
-
- tickets_triaged_total
|
|
536
|
-
- tickets_auto_replied_total
|
|
537
|
-
- tickets_escalated_total
|
|
538
|
-
- average_confidence_score
|
|
539
|
-
- average_response_time_seconds
|
|
540
|
-
- sla_compliance_rate
|
|
541
|
-
- customer_satisfaction_score
|
|
542
|
-
|
|
543
|
-
traces:
|
|
544
|
-
enabled: true
|
|
545
|
-
exporter: jaeger
|
|
546
|
-
|
|
547
|
-
logs:
|
|
548
|
-
level: info
|
|
549
|
-
format: json
|
|
550
|
-
|
|
551
|
-
metadata:
|
|
552
|
-
version: 2.5.0
|
|
553
|
-
author:
|
|
554
|
-
name: Support Team
|
|
555
|
-
email: support@example.com
|
|
556
|
-
license: Proprietary
|
|
557
|
-
tags:
|
|
558
|
-
- customer-support
|
|
559
|
-
- ticket-triage
|
|
560
|
-
- automation
|
|
561
|
-
- ai-assistant
|
|
562
|
-
documentation_url: https://docs.example.com/agents/support-triage
|
|
563
|
-
```
|
|
564
|
-
|
|
565
|
-
## Implementation (TypeScript)
|
|
566
|
-
|
|
567
|
-
```typescript
|
|
568
|
-
/**
|
|
569
|
-
* Customer Support Ticket Triage Agent
|
|
570
|
-
*
|
|
571
|
-
* Production-ready OSSA agent for intelligent support ticket triage,
|
|
572
|
-
* classification, routing, and automated responses.
|
|
573
|
-
*/
|
|
574
|
-
|
|
575
|
-
import { Agent, OSSARuntime } from '@ossa/runtime';
|
|
576
|
-
import { OpenAI } from 'openai';
|
|
577
|
-
import { Pinecone } from '@pinecone-database/pinecone';
|
|
578
|
-
import axios from 'axios';
|
|
579
|
-
|
|
580
|
-
interface TriageInput {
|
|
581
|
-
ticketId: string;
|
|
582
|
-
subject: string;
|
|
583
|
-
body: string;
|
|
584
|
-
customerId: string;
|
|
585
|
-
customerTier?: 'free' | 'basic' | 'pro' | 'enterprise';
|
|
586
|
-
channel?: string;
|
|
587
|
-
attachments?: Array<{filename: string; url: string; contentType: string}>;
|
|
588
|
-
metadata?: Record<string, any>;
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
interface TriageResult {
|
|
592
|
-
ticketId: string;
|
|
593
|
-
category: string;
|
|
594
|
-
subcategory?: string;
|
|
595
|
-
priority: 'critical' | 'high' | 'normal' | 'low';
|
|
596
|
-
priorityScore: number;
|
|
597
|
-
routing: {
|
|
598
|
-
team: string;
|
|
599
|
-
suggestedAgent?: string;
|
|
600
|
-
skillsRequired: string[];
|
|
601
|
-
};
|
|
602
|
-
sentiment: {
|
|
603
|
-
score: number;
|
|
604
|
-
label: string;
|
|
605
|
-
angry: boolean;
|
|
606
|
-
frustrated: boolean;
|
|
607
|
-
};
|
|
608
|
-
intent: string[];
|
|
609
|
-
entities: Record<string, any>;
|
|
610
|
-
knowledgeBaseMatches: Array<{
|
|
611
|
-
articleId: string;
|
|
612
|
-
title: string;
|
|
613
|
-
url: string;
|
|
614
|
-
relevanceScore: number;
|
|
615
|
-
snippet: string;
|
|
616
|
-
}>;
|
|
617
|
-
suggestedResponse?: string;
|
|
618
|
-
confidence: number;
|
|
619
|
-
action: 'auto_reply' | 'escalate' | 'assign' | 'pending_info';
|
|
620
|
-
escalationReason?: string;
|
|
621
|
-
slaDeadline: Date;
|
|
622
|
-
tags: string[];
|
|
623
|
-
timestamp: Date;
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
export class SupportTriageAgent extends Agent {
|
|
627
|
-
private openai: OpenAI;
|
|
628
|
-
private pinecone: Pinecone;
|
|
629
|
-
private zendeskBaseUrl: string;
|
|
630
|
-
private zendeskToken: string;
|
|
631
|
-
|
|
632
|
-
constructor(runtime: OSSARuntime) {
|
|
633
|
-
super(runtime);
|
|
634
|
-
|
|
635
|
-
this.openai = new OpenAI({
|
|
636
|
-
apiKey: process.env.OPENAI_API_KEY,
|
|
637
|
-
});
|
|
638
|
-
|
|
639
|
-
this.pinecone = new Pinecone({
|
|
640
|
-
apiKey: process.env.PINECONE_API_KEY || '',
|
|
641
|
-
});
|
|
642
|
-
|
|
643
|
-
this.zendeskBaseUrl = process.env.ZENDESK_BASE_URL || '';
|
|
644
|
-
this.zendeskToken = process.env.ZENDESK_API_TOKEN || '';
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
/**
|
|
648
|
-
* Main triage capability
|
|
649
|
-
*/
|
|
650
|
-
async triageTicket(input: TriageInput): Promise<TriageResult> {
|
|
651
|
-
const startTime = Date.now();
|
|
652
|
-
|
|
653
|
-
this.logger.info(`Starting triage for ticket ${input.ticketId}`);
|
|
654
|
-
|
|
655
|
-
try {
|
|
656
|
-
// Run classification, sentiment, and KB search in parallel
|
|
657
|
-
const [classification, sentiment, kbMatches] = await Promise.all([
|
|
658
|
-
this.classifyTicket(input),
|
|
659
|
-
this.analyzeSentiment(input.body),
|
|
660
|
-
this.searchKnowledgeBase(input.subject + ' ' + input.body),
|
|
661
|
-
]);
|
|
662
|
-
|
|
663
|
-
// Calculate priority
|
|
664
|
-
const priority = this.calculatePriority({
|
|
665
|
-
classification,
|
|
666
|
-
sentiment,
|
|
667
|
-
customerTier: input.customerTier || 'basic',
|
|
668
|
-
});
|
|
669
|
-
|
|
670
|
-
// Determine routing
|
|
671
|
-
const routing = this.determineRouting(classification, input);
|
|
672
|
-
|
|
673
|
-
// Extract intents and entities
|
|
674
|
-
const { intent, entities } = await this.extractIntentAndEntities(input.body);
|
|
675
|
-
|
|
676
|
-
// Generate response suggestion if confidence is high
|
|
677
|
-
let suggestedResponse: string | undefined;
|
|
678
|
-
let confidence = classification.confidence;
|
|
679
|
-
|
|
680
|
-
if (confidence > 0.9 && kbMatches.length > 0) {
|
|
681
|
-
suggestedResponse = await this.generateResponse({
|
|
682
|
-
ticketContent: input.body,
|
|
683
|
-
knowledgeArticles: kbMatches,
|
|
684
|
-
tone: this.selectTone(sentiment),
|
|
685
|
-
});
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// Determine action
|
|
689
|
-
const action = this.determineAction({
|
|
690
|
-
confidence,
|
|
691
|
-
sentiment,
|
|
692
|
-
customerTier: input.customerTier,
|
|
693
|
-
category: classification.category,
|
|
694
|
-
});
|
|
695
|
-
|
|
696
|
-
// Calculate SLA deadline
|
|
697
|
-
const slaDeadline = this.calculateSlaDeadline(priority.level);
|
|
698
|
-
|
|
699
|
-
// Build result
|
|
700
|
-
const result: TriageResult = {
|
|
701
|
-
ticketId: input.ticketId,
|
|
702
|
-
category: classification.category,
|
|
703
|
-
subcategory: classification.subcategory,
|
|
704
|
-
priority: priority.level,
|
|
705
|
-
priorityScore: priority.score,
|
|
706
|
-
routing,
|
|
707
|
-
sentiment,
|
|
708
|
-
intent,
|
|
709
|
-
entities,
|
|
710
|
-
knowledgeBaseMatches: kbMatches,
|
|
711
|
-
suggestedResponse,
|
|
712
|
-
confidence,
|
|
713
|
-
action,
|
|
714
|
-
escalationReason: action === 'escalate' ? this.getEscalationReason(sentiment, input.customerTier) : undefined,
|
|
715
|
-
slaDeadline,
|
|
716
|
-
tags: this.generateTags(classification, sentiment, input),
|
|
717
|
-
timestamp: new Date(),
|
|
718
|
-
};
|
|
719
|
-
|
|
720
|
-
// Execute action
|
|
721
|
-
await this.executeAction(result);
|
|
722
|
-
|
|
723
|
-
// Record metrics
|
|
724
|
-
const duration = Date.now() - startTime;
|
|
725
|
-
this.metrics.histogram('triage_duration_seconds', duration / 1000);
|
|
726
|
-
this.metrics.counter('tickets_triaged_total', { category: result.category, action: result.action });
|
|
727
|
-
this.metrics.gauge('average_confidence_score', confidence);
|
|
728
|
-
|
|
729
|
-
this.logger.info(`Triage completed for ticket ${input.ticketId}: ${action}`);
|
|
730
|
-
|
|
731
|
-
return result;
|
|
732
|
-
|
|
733
|
-
} catch (error) {
|
|
734
|
-
this.logger.error(`Triage failed for ticket ${input.ticketId}:`, error);
|
|
735
|
-
this.metrics.counter('triage_errors_total');
|
|
736
|
-
throw error;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
|
|
740
|
-
/**
|
|
741
|
-
* Classify ticket using GPT-4
|
|
742
|
-
*/
|
|
743
|
-
private async classifyTicket(input: TriageInput): Promise<{
|
|
744
|
-
category: string;
|
|
745
|
-
subcategory?: string;
|
|
746
|
-
confidence: number;
|
|
747
|
-
}> {
|
|
748
|
-
const prompt = `
|
|
749
|
-
Classify the following customer support ticket into one of these categories:
|
|
750
|
-
- billing (payment issues, invoices, refunds, subscriptions)
|
|
751
|
-
- technical (bugs, errors, crashes, not working)
|
|
752
|
-
- feature_request (new features, enhancements)
|
|
753
|
-
- bug_report (software bugs, defects)
|
|
754
|
-
- account_management (login, password, settings)
|
|
755
|
-
- general_inquiry (questions, how-to)
|
|
756
|
-
- complaint (dissatisfaction, problems)
|
|
757
|
-
- feedback (suggestions, comments)
|
|
758
|
-
|
|
759
|
-
Ticket:
|
|
760
|
-
Subject: ${input.subject}
|
|
761
|
-
Body: ${input.body}
|
|
762
|
-
|
|
763
|
-
Return JSON: {"category": "...", "subcategory": "...", "confidence": 0.0-1.0, "reasoning": "..."}
|
|
764
|
-
`.trim();
|
|
765
|
-
|
|
766
|
-
const response = await this.openai.chat.completions.create({
|
|
767
|
-
model: 'gpt-4-turbo-preview',
|
|
768
|
-
messages: [
|
|
769
|
-
{ role: 'system', content: 'You are an expert customer support ticket classifier.' },
|
|
770
|
-
{ role: 'user', content: prompt },
|
|
771
|
-
],
|
|
772
|
-
response_format: { type: 'json_object' },
|
|
773
|
-
});
|
|
774
|
-
|
|
775
|
-
const result = JSON.parse(response.choices[0].message.content || '{}');
|
|
776
|
-
|
|
777
|
-
return {
|
|
778
|
-
category: result.category,
|
|
779
|
-
subcategory: result.subcategory,
|
|
780
|
-
confidence: result.confidence,
|
|
781
|
-
};
|
|
782
|
-
}
|
|
783
|
-
|
|
784
|
-
/**
|
|
785
|
-
* Analyze sentiment
|
|
786
|
-
*/
|
|
787
|
-
private async analyzeSentiment(text: string): Promise<{
|
|
788
|
-
score: number;
|
|
789
|
-
label: string;
|
|
790
|
-
angry: boolean;
|
|
791
|
-
frustrated: boolean;
|
|
792
|
-
}> {
|
|
793
|
-
const prompt = `
|
|
794
|
-
Analyze the sentiment and emotional tone of this customer message:
|
|
795
|
-
|
|
796
|
-
"${text}"
|
|
797
|
-
|
|
798
|
-
Return JSON: {
|
|
799
|
-
"score": -1.0 to 1.0,
|
|
800
|
-
"label": "very_negative" | "negative" | "neutral" | "positive" | "very_positive",
|
|
801
|
-
"angry": boolean,
|
|
802
|
-
"frustrated": boolean
|
|
803
|
-
}
|
|
804
|
-
`.trim();
|
|
805
|
-
|
|
806
|
-
const response = await this.openai.chat.completions.create({
|
|
807
|
-
model: 'gpt-4-turbo-preview',
|
|
808
|
-
messages: [{ role: 'user', content: prompt }],
|
|
809
|
-
response_format: { type: 'json_object' },
|
|
810
|
-
});
|
|
811
|
-
|
|
812
|
-
return JSON.parse(response.choices[0].message.content || '{}');
|
|
813
|
-
}
|
|
814
|
-
|
|
815
|
-
/**
|
|
816
|
-
* Search knowledge base using vector embeddings
|
|
817
|
-
*/
|
|
818
|
-
private async searchKnowledgeBase(query: string, limit: number = 5): Promise<any[]> {
|
|
819
|
-
// Generate embedding for query
|
|
820
|
-
const embeddingResponse = await this.openai.embeddings.create({
|
|
821
|
-
model: 'text-embedding-ada-002',
|
|
822
|
-
input: query,
|
|
823
|
-
});
|
|
824
|
-
|
|
825
|
-
const queryEmbedding = embeddingResponse.data[0].embedding;
|
|
826
|
-
|
|
827
|
-
// Search Pinecone
|
|
828
|
-
const index = this.pinecone.Index('support-kb');
|
|
829
|
-
const searchResults = await index.query({
|
|
830
|
-
vector: queryEmbedding,
|
|
831
|
-
topK: limit,
|
|
832
|
-
includeMetadata: true,
|
|
833
|
-
});
|
|
834
|
-
|
|
835
|
-
return searchResults.matches?.map(match => ({
|
|
836
|
-
articleId: match.id,
|
|
837
|
-
title: match.metadata?.title,
|
|
838
|
-
url: match.metadata?.url,
|
|
839
|
-
relevanceScore: match.score,
|
|
840
|
-
snippet: match.metadata?.snippet,
|
|
841
|
-
})) || [];
|
|
842
|
-
}
|
|
843
|
-
|
|
844
|
-
/**
|
|
845
|
-
* Generate response suggestion
|
|
846
|
-
*/
|
|
847
|
-
private async generateResponse(params: {
|
|
848
|
-
ticketContent: string;
|
|
849
|
-
knowledgeArticles: any[];
|
|
850
|
-
tone: string;
|
|
851
|
-
}): Promise<string> {
|
|
852
|
-
const kbContext = params.knowledgeArticles
|
|
853
|
-
.map(a => `Article: ${a.title}\n${a.snippet}`)
|
|
854
|
-
.join('\n\n');
|
|
855
|
-
|
|
856
|
-
const prompt = `
|
|
857
|
-
You are a customer support agent. Generate a helpful response to this customer ticket.
|
|
858
|
-
|
|
859
|
-
Customer message:
|
|
860
|
-
${params.ticketContent}
|
|
861
|
-
|
|
862
|
-
Relevant knowledge base articles:
|
|
863
|
-
${kbContext}
|
|
864
|
-
|
|
865
|
-
Tone: ${params.tone}
|
|
866
|
-
|
|
867
|
-
Generate a response that:
|
|
868
|
-
1. Addresses the customer's question/issue
|
|
869
|
-
2. References the knowledge base articles
|
|
870
|
-
3. Is clear, concise, and helpful
|
|
871
|
-
4. Uses the specified tone
|
|
872
|
-
`.trim();
|
|
873
|
-
|
|
874
|
-
const response = await this.openai.chat.completions.create({
|
|
875
|
-
model: 'gpt-4-turbo-preview',
|
|
876
|
-
messages: [
|
|
877
|
-
{ role: 'system', content: 'You are a helpful, empathetic customer support agent.' },
|
|
878
|
-
{ role: 'user', content: prompt },
|
|
879
|
-
],
|
|
880
|
-
});
|
|
881
|
-
|
|
882
|
-
return response.choices[0].message.content || '';
|
|
883
|
-
}
|
|
884
|
-
|
|
885
|
-
/**
|
|
886
|
-
* Extract intent and entities
|
|
887
|
-
*/
|
|
888
|
-
private async extractIntentAndEntities(text: string): Promise<{
|
|
889
|
-
intent: string[];
|
|
890
|
-
entities: Record<string, any>;
|
|
891
|
-
}> {
|
|
892
|
-
const prompt = `
|
|
893
|
-
Extract the customer's intents and entities from this message:
|
|
894
|
-
|
|
895
|
-
"${text}"
|
|
896
|
-
|
|
897
|
-
Return JSON: {
|
|
898
|
-
"intent": ["intent1", "intent2"],
|
|
899
|
-
"entities": {
|
|
900
|
-
"product": "...",
|
|
901
|
-
"error_code": "...",
|
|
902
|
-
"date": "...",
|
|
903
|
-
...
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
`.trim();
|
|
907
|
-
|
|
908
|
-
const response = await this.openai.chat.completions.create({
|
|
909
|
-
model: 'gpt-4-turbo-preview',
|
|
910
|
-
messages: [{ role: 'user', content: prompt }],
|
|
911
|
-
response_format: { type: 'json_object' },
|
|
912
|
-
});
|
|
913
|
-
|
|
914
|
-
return JSON.parse(response.choices[0].message.content || '{}');
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
/**
|
|
918
|
-
* Calculate priority
|
|
919
|
-
*/
|
|
920
|
-
private calculatePriority(params: {
|
|
921
|
-
classification: any;
|
|
922
|
-
sentiment: any;
|
|
923
|
-
customerTier: string;
|
|
924
|
-
}): { level: 'critical' | 'high' | 'normal' | 'low'; score: number } {
|
|
925
|
-
let score = 50; // Base score
|
|
926
|
-
|
|
927
|
-
// Customer tier bonus
|
|
928
|
-
const tierBonus = { free: 0, basic: 10, pro: 20, enterprise: 40 };
|
|
929
|
-
score += tierBonus[params.customerTier] || 0;
|
|
930
|
-
|
|
931
|
-
// Category urgency
|
|
932
|
-
if (params.classification.category === 'bug_report') score += 20;
|
|
933
|
-
if (params.classification.category === 'billing') score += 15;
|
|
934
|
-
if (params.classification.category === 'technical') score += 10;
|
|
935
|
-
|
|
936
|
-
// Sentiment impact
|
|
937
|
-
if (params.sentiment.angry) score += 30;
|
|
938
|
-
if (params.sentiment.frustrated) score += 15;
|
|
939
|
-
if (params.sentiment.score < -0.5) score += 20;
|
|
940
|
-
|
|
941
|
-
// Determine level
|
|
942
|
-
let level: 'critical' | 'high' | 'normal' | 'low';
|
|
943
|
-
if (score >= 80) level = 'critical';
|
|
944
|
-
else if (score >= 60) level = 'high';
|
|
945
|
-
else if (score >= 40) level = 'normal';
|
|
946
|
-
else level = 'low';
|
|
947
|
-
|
|
948
|
-
return { level, score };
|
|
949
|
-
}
|
|
950
|
-
|
|
951
|
-
/**
|
|
952
|
-
* Determine routing
|
|
953
|
-
*/
|
|
954
|
-
private determineRouting(classification: any, input: TriageInput): any {
|
|
955
|
-
const categoryToTeam = {
|
|
956
|
-
billing: 'billing',
|
|
957
|
-
technical: 'engineering',
|
|
958
|
-
feature_request: 'product',
|
|
959
|
-
bug_report: 'engineering',
|
|
960
|
-
account_management: 'success',
|
|
961
|
-
general_inquiry: 'general',
|
|
962
|
-
complaint: 'success',
|
|
963
|
-
feedback: 'product',
|
|
964
|
-
};
|
|
965
|
-
|
|
966
|
-
return {
|
|
967
|
-
team: categoryToTeam[classification.category] || 'general',
|
|
968
|
-
skillsRequired: this.getRequiredSkills(classification.category),
|
|
969
|
-
};
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
/**
|
|
973
|
-
* Determine action
|
|
974
|
-
*/
|
|
975
|
-
private determineAction(params: {
|
|
976
|
-
confidence: number;
|
|
977
|
-
sentiment: any;
|
|
978
|
-
customerTier?: string;
|
|
979
|
-
category: string;
|
|
980
|
-
}): 'auto_reply' | 'escalate' | 'assign' | 'pending_info' {
|
|
981
|
-
// Never auto-reply to enterprise customers
|
|
982
|
-
if (params.customerTier === 'enterprise') return 'escalate';
|
|
983
|
-
|
|
984
|
-
// Never auto-reply to angry customers
|
|
985
|
-
if (params.sentiment.angry) return 'escalate';
|
|
986
|
-
|
|
987
|
-
// Never auto-reply to complaints or legal issues
|
|
988
|
-
if (['complaint', 'legal'].includes(params.category)) return 'escalate';
|
|
989
|
-
|
|
990
|
-
// Auto-reply if high confidence
|
|
991
|
-
if (params.confidence >= 0.95) return 'auto_reply';
|
|
992
|
-
|
|
993
|
-
// Escalate if low confidence
|
|
994
|
-
if (params.confidence < 0.6) return 'escalate';
|
|
995
|
-
|
|
996
|
-
// Otherwise assign to human
|
|
997
|
-
return 'assign';
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
/**
|
|
1001
|
-
* Execute action
|
|
1002
|
-
*/
|
|
1003
|
-
private async executeAction(result: TriageResult): Promise<void> {
|
|
1004
|
-
if (result.action === 'auto_reply' && result.suggestedResponse) {
|
|
1005
|
-
await this.sendAutoReply(result.ticketId, result.suggestedResponse);
|
|
1006
|
-
this.metrics.counter('tickets_auto_replied_total');
|
|
1007
|
-
} else if (result.action === 'escalate') {
|
|
1008
|
-
await this.escalateTicket(result.ticketId, result.escalationReason || 'Unknown');
|
|
1009
|
-
this.metrics.counter('tickets_escalated_total');
|
|
1010
|
-
} else if (result.action === 'assign') {
|
|
1011
|
-
await this.assignTicket(result.ticketId, result.routing.team);
|
|
1012
|
-
}
|
|
1013
|
-
}
|
|
1014
|
-
|
|
1015
|
-
/**
|
|
1016
|
-
* Send auto-reply via Zendesk
|
|
1017
|
-
*/
|
|
1018
|
-
private async sendAutoReply(ticketId: string, response: string): Promise<void> {
|
|
1019
|
-
await axios.put(
|
|
1020
|
-
`${this.zendeskBaseUrl}/tickets/${ticketId}.json`,
|
|
1021
|
-
{
|
|
1022
|
-
ticket: {
|
|
1023
|
-
comment: {
|
|
1024
|
-
body: response,
|
|
1025
|
-
public: true,
|
|
1026
|
-
author_id: 'support-bot',
|
|
1027
|
-
},
|
|
1028
|
-
status: 'solved',
|
|
1029
|
-
},
|
|
1030
|
-
},
|
|
1031
|
-
{
|
|
1032
|
-
headers: {
|
|
1033
|
-
'Authorization': `Bearer ${this.zendeskToken}`,
|
|
1034
|
-
'Content-Type': 'application/json',
|
|
1035
|
-
},
|
|
1036
|
-
}
|
|
1037
|
-
);
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
/**
|
|
1041
|
-
* Escalate ticket
|
|
1042
|
-
*/
|
|
1043
|
-
private async escalateTicket(ticketId: string, reason: string): Promise<void> {
|
|
1044
|
-
// Send Slack notification
|
|
1045
|
-
await this.sendSlackAlert({
|
|
1046
|
-
ticketId,
|
|
1047
|
-
message: `🚨 Ticket escalated: ${reason}`,
|
|
1048
|
-
urgency: 'high',
|
|
1049
|
-
});
|
|
1050
|
-
|
|
1051
|
-
// Update ticket priority in Zendesk
|
|
1052
|
-
await axios.put(
|
|
1053
|
-
`${this.zendeskBaseUrl}/tickets/${ticketId}.json`,
|
|
1054
|
-
{
|
|
1055
|
-
ticket: {
|
|
1056
|
-
priority: 'urgent',
|
|
1057
|
-
tags: ['escalated', 'needs-human'],
|
|
1058
|
-
},
|
|
1059
|
-
},
|
|
1060
|
-
{
|
|
1061
|
-
headers: {
|
|
1062
|
-
'Authorization': `Bearer ${this.zendeskToken}`,
|
|
1063
|
-
'Content-Type': 'application/json',
|
|
1064
|
-
},
|
|
1065
|
-
}
|
|
1066
|
-
);
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
/**
|
|
1070
|
-
* Assign ticket to team
|
|
1071
|
-
*/
|
|
1072
|
-
private async assignTicket(ticketId: string, team: string): Promise<void> {
|
|
1073
|
-
// Update ticket in Zendesk
|
|
1074
|
-
await axios.put(
|
|
1075
|
-
`${this.zendeskBaseUrl}/tickets/${ticketId}.json`,
|
|
1076
|
-
{
|
|
1077
|
-
ticket: {
|
|
1078
|
-
group_id: this.getTeamGroupId(team),
|
|
1079
|
-
tags: ['triaged', `team-${team}`],
|
|
1080
|
-
},
|
|
1081
|
-
},
|
|
1082
|
-
{
|
|
1083
|
-
headers: {
|
|
1084
|
-
'Authorization': `Bearer ${this.zendeskToken}`,
|
|
1085
|
-
'Content-Type': 'application/json',
|
|
1086
|
-
},
|
|
1087
|
-
}
|
|
1088
|
-
);
|
|
1089
|
-
}
|
|
1090
|
-
|
|
1091
|
-
// Helper methods
|
|
1092
|
-
private selectTone(sentiment: any): string {
|
|
1093
|
-
if (sentiment.angry || sentiment.frustrated) return 'empathetic';
|
|
1094
|
-
if (sentiment.score > 0.5) return 'friendly';
|
|
1095
|
-
return 'professional';
|
|
1096
|
-
}
|
|
1097
|
-
|
|
1098
|
-
private getEscalationReason(sentiment: any, customerTier?: string): string {
|
|
1099
|
-
if (customerTier === 'enterprise') return 'high_value_customer';
|
|
1100
|
-
if (sentiment.angry) return 'angry_customer';
|
|
1101
|
-
return 'low_confidence';
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
private calculateSlaDeadline(priority: string): Date {
|
|
1105
|
-
const slaMinutes = { critical: 15, high: 120, normal: 1440, low: 2880 };
|
|
1106
|
-
const minutes = slaMinutes[priority] || 1440;
|
|
1107
|
-
return new Date(Date.now() + minutes * 60 * 1000);
|
|
1108
|
-
}
|
|
1109
|
-
|
|
1110
|
-
private generateTags(classification: any, sentiment: any, input: TriageInput): string[] {
|
|
1111
|
-
const tags = [classification.category];
|
|
1112
|
-
if (sentiment.angry) tags.push('angry');
|
|
1113
|
-
if (sentiment.frustrated) tags.push('frustrated');
|
|
1114
|
-
if (input.customerTier) tags.push(`tier-${input.customerTier}`);
|
|
1115
|
-
return tags;
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
|
-
private getRequiredSkills(category: string): string[] {
|
|
1119
|
-
const skillsMap = {
|
|
1120
|
-
billing: ['payments', 'accounting'],
|
|
1121
|
-
technical: ['debugging', 'api'],
|
|
1122
|
-
feature_request: ['product_knowledge'],
|
|
1123
|
-
bug_report: ['debugging', 'qa'],
|
|
1124
|
-
};
|
|
1125
|
-
return skillsMap[category] || [];
|
|
1126
|
-
}
|
|
1127
|
-
|
|
1128
|
-
private getTeamGroupId(team: string): string {
|
|
1129
|
-
// Map team names to Zendesk group IDs
|
|
1130
|
-
return '12345';
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
|
-
private async sendSlackAlert(params: any): Promise<void> {
|
|
1134
|
-
// Send Slack notification
|
|
1135
|
-
this.logger.info(`Slack alert: ${params.message}`);
|
|
1136
|
-
}
|
|
1137
|
-
}
|
|
1138
|
-
|
|
1139
|
-
// Entry point
|
|
1140
|
-
async function main() {
|
|
1141
|
-
const runtime = new OSSARuntime({
|
|
1142
|
-
manifestPath: '/etc/ossa/manifest.yaml',
|
|
1143
|
-
});
|
|
1144
|
-
|
|
1145
|
-
const agent = new SupportTriageAgent(runtime);
|
|
1146
|
-
await agent.start();
|
|
1147
|
-
}
|
|
1148
|
-
|
|
1149
|
-
main().catch(console.error);
|
|
1150
|
-
```
|
|
1151
|
-
|
|
1152
|
-
## Deployment Instructions
|
|
1153
|
-
|
|
1154
|
-
### Step 1: Deploy to Kubernetes
|
|
1155
|
-
|
|
1156
|
-
```bash
|
|
1157
|
-
kubectl apply -f - <<EOF
|
|
1158
|
-
apiVersion: apps/v1
|
|
1159
|
-
kind: Deployment
|
|
1160
|
-
metadata:
|
|
1161
|
-
name: support-triage-agent
|
|
1162
|
-
namespace: customer-support
|
|
1163
|
-
spec:
|
|
1164
|
-
replicas: 3
|
|
1165
|
-
selector:
|
|
1166
|
-
matchLabels:
|
|
1167
|
-
app: support-triage
|
|
1168
|
-
template:
|
|
1169
|
-
metadata:
|
|
1170
|
-
labels:
|
|
1171
|
-
app: support-triage
|
|
1172
|
-
spec:
|
|
1173
|
-
containers:
|
|
1174
|
-
- name: agent
|
|
1175
|
-
image: registry.example.com/agents/support-triage:2.5.0
|
|
1176
|
-
env:
|
|
1177
|
-
- name: OPENAI_API_KEY
|
|
1178
|
-
valueFrom:
|
|
1179
|
-
secretKeyRef:
|
|
1180
|
-
name: ai-keys
|
|
1181
|
-
key: openai
|
|
1182
|
-
- name: ZENDESK_API_TOKEN
|
|
1183
|
-
valueFrom:
|
|
1184
|
-
secretKeyRef:
|
|
1185
|
-
name: support-keys
|
|
1186
|
-
key: zendesk
|
|
1187
|
-
- name: PINECONE_API_KEY
|
|
1188
|
-
valueFrom:
|
|
1189
|
-
secretKeyRef:
|
|
1190
|
-
name: ai-keys
|
|
1191
|
-
key: pinecone
|
|
1192
|
-
resources:
|
|
1193
|
-
requests:
|
|
1194
|
-
cpu: 500m
|
|
1195
|
-
memory: 1Gi
|
|
1196
|
-
limits:
|
|
1197
|
-
cpu: 2000m
|
|
1198
|
-
memory: 4Gi
|
|
1199
|
-
ports:
|
|
1200
|
-
- containerPort: 8080
|
|
1201
|
-
EOF
|
|
1202
|
-
```
|
|
1203
|
-
|
|
1204
|
-
### Step 2: Configure Zendesk Webhook
|
|
1205
|
-
|
|
1206
|
-
```bash
|
|
1207
|
-
# In Zendesk Admin → Extensions → Webhooks
|
|
1208
|
-
# Create webhook pointing to: https://support-triage.example.com/webhooks/zendesk
|
|
1209
|
-
# Events: Ticket Created, Ticket Updated
|
|
1210
|
-
```
|
|
1211
|
-
|
|
1212
|
-
## Production Checklist
|
|
1213
|
-
|
|
1214
|
-
- [ ] Knowledge base indexed in Pinecone
|
|
1215
|
-
- [ ] Auto-reply confidence threshold tested
|
|
1216
|
-
- [ ] Escalation rules validated with support team
|
|
1217
|
-
- [ ] SLA deadlines configured per tier
|
|
1218
|
-
- [ ] Slack alerts configured
|
|
1219
|
-
- [ ] Human review sample rate set
|
|
1220
|
-
- [ ] Cost monitoring enabled
|
|
1221
|
-
- [ ] Sentiment analysis accuracy tested
|
|
1222
|
-
- [ ] Team routing rules validated
|
|
1223
|
-
|
|
1224
|
-
## Cost Management
|
|
1225
|
-
|
|
1226
|
-
- **Monthly budget**: $500
|
|
1227
|
-
- **Per-ticket limit**: $0.50
|
|
1228
|
-
- **Optimization**: Cache KB searches, batch processing, use cheaper models when possible
|
|
1229
|
-
|
|
1230
|
-
## Further Reading
|
|
1231
|
-
|
|
1232
|
-
- [Zendesk API Documentation](https://developer.zendesk.com/)
|
|
1233
|
-
- [OpenAI Embeddings Guide](https://platform.openai.com/docs/guides/embeddings)
|
|
1234
|
-
- [OSSA Runtime Documentation](https://openstandardagents.org/docs/runtime)
|