agentic-lang 0.2.0

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.
Files changed (146) hide show
  1. package/COMMUNITY.md +220 -0
  2. package/CONTRIBUTING.md +194 -0
  3. package/FINAL_REPORT.md +398 -0
  4. package/FOR_OTHER_LLMS.md +286 -0
  5. package/IMPROVEMENTS.md +319 -0
  6. package/LAUNCH_GUIDE.md +388 -0
  7. package/LICENSE +21 -0
  8. package/NPM_PUBLISH.md +257 -0
  9. package/PROJECT_COMPLETE.md +414 -0
  10. package/PROJECT_OVERVIEW.md +265 -0
  11. package/PROJECT_TREE.txt +228 -0
  12. package/PUBLISHING_GUIDE.md +426 -0
  13. package/PUBLISH_NOW.md +337 -0
  14. package/QUICKSTART.md +207 -0
  15. package/README.md +195 -0
  16. package/README_ENHANCED.md +329 -0
  17. package/READY_TO_LAUNCH.txt +56 -0
  18. package/REFACTOR_PLAN.md +179 -0
  19. package/ROADMAP.md +201 -0
  20. package/SUMMARY.md +315 -0
  21. package/bin/agentic.js +3 -0
  22. package/blog/001-introducing-agentic.md +382 -0
  23. package/blog/002-confidence-driven-development.md +490 -0
  24. package/blog/003-formal-verification.md +427 -0
  25. package/blog/004-multi-agent-production.md +436 -0
  26. package/dist/cli.d.ts +7 -0
  27. package/dist/cli.d.ts.map +1 -0
  28. package/dist/cli.js +151 -0
  29. package/dist/cli.js.map +1 -0
  30. package/dist/diagnostics/diagnostic.d.ts +115 -0
  31. package/dist/diagnostics/diagnostic.d.ts.map +1 -0
  32. package/dist/diagnostics/diagnostic.js +101 -0
  33. package/dist/diagnostics/diagnostic.js.map +1 -0
  34. package/dist/diagnostics/formatter.d.ts +36 -0
  35. package/dist/diagnostics/formatter.d.ts.map +1 -0
  36. package/dist/diagnostics/formatter.js +263 -0
  37. package/dist/diagnostics/formatter.js.map +1 -0
  38. package/dist/effects/effect-system.d.ts +64 -0
  39. package/dist/effects/effect-system.d.ts.map +1 -0
  40. package/dist/effects/effect-system.js +197 -0
  41. package/dist/effects/effect-system.js.map +1 -0
  42. package/dist/generator/typescript-generator.d.ts +31 -0
  43. package/dist/generator/typescript-generator.d.ts.map +1 -0
  44. package/dist/generator/typescript-generator.js +308 -0
  45. package/dist/generator/typescript-generator.js.map +1 -0
  46. package/dist/index.d.ts +19 -0
  47. package/dist/index.d.ts.map +1 -0
  48. package/dist/index.js +60 -0
  49. package/dist/index.js.map +1 -0
  50. package/dist/lean4/exporter.d.ts +24 -0
  51. package/dist/lean4/exporter.d.ts.map +1 -0
  52. package/dist/lean4/exporter.js +142 -0
  53. package/dist/lean4/exporter.js.map +1 -0
  54. package/dist/lsp/server.d.ts +6 -0
  55. package/dist/lsp/server.d.ts.map +1 -0
  56. package/dist/lsp/server.js +131 -0
  57. package/dist/lsp/server.js.map +1 -0
  58. package/dist/parser/lexer.d.ts +79 -0
  59. package/dist/parser/lexer.d.ts.map +1 -0
  60. package/dist/parser/lexer.js +296 -0
  61. package/dist/parser/lexer.js.map +1 -0
  62. package/dist/parser/parser-enhanced.d.ts +12 -0
  63. package/dist/parser/parser-enhanced.d.ts.map +1 -0
  64. package/dist/parser/parser-enhanced.js +206 -0
  65. package/dist/parser/parser-enhanced.js.map +1 -0
  66. package/dist/parser/parser.d.ts +34 -0
  67. package/dist/parser/parser.d.ts.map +1 -0
  68. package/dist/parser/parser.js +507 -0
  69. package/dist/parser/parser.js.map +1 -0
  70. package/dist/property-tests/generator-enhanced.d.ts +27 -0
  71. package/dist/property-tests/generator-enhanced.d.ts.map +1 -0
  72. package/dist/property-tests/generator-enhanced.js +209 -0
  73. package/dist/property-tests/generator-enhanced.js.map +1 -0
  74. package/dist/property-tests/generator-fixed.d.ts +2 -0
  75. package/dist/property-tests/generator-fixed.d.ts.map +1 -0
  76. package/dist/property-tests/generator-fixed.js +7 -0
  77. package/dist/property-tests/generator-fixed.js.map +1 -0
  78. package/dist/property-tests/generator.d.ts +28 -0
  79. package/dist/property-tests/generator.d.ts.map +1 -0
  80. package/dist/property-tests/generator.js +284 -0
  81. package/dist/property-tests/generator.js.map +1 -0
  82. package/dist/refinements/refinement-types.d.ts +96 -0
  83. package/dist/refinements/refinement-types.d.ts.map +1 -0
  84. package/dist/refinements/refinement-types.js +234 -0
  85. package/dist/refinements/refinement-types.js.map +1 -0
  86. package/dist/repl.d.ts +21 -0
  87. package/dist/repl.d.ts.map +1 -0
  88. package/dist/repl.js +317 -0
  89. package/dist/repl.js.map +1 -0
  90. package/dist/runtime/agents.d.ts +97 -0
  91. package/dist/runtime/agents.d.ts.map +1 -0
  92. package/dist/runtime/agents.js +258 -0
  93. package/dist/runtime/agents.js.map +1 -0
  94. package/dist/runtime/index.d.ts +98 -0
  95. package/dist/runtime/index.d.ts.map +1 -0
  96. package/dist/runtime/index.js +253 -0
  97. package/dist/runtime/index.js.map +1 -0
  98. package/dist/types-extended.d.ts +197 -0
  99. package/dist/types-extended.d.ts.map +1 -0
  100. package/dist/types-extended.js +7 -0
  101. package/dist/types-extended.js.map +1 -0
  102. package/dist/types.d.ts +129 -0
  103. package/dist/types.d.ts.map +1 -0
  104. package/dist/types.js +6 -0
  105. package/dist/types.js.map +1 -0
  106. package/dist/verification/z3-engine.d.ts +75 -0
  107. package/dist/verification/z3-engine.d.ts.map +1 -0
  108. package/dist/verification/z3-engine.js +234 -0
  109. package/dist/verification/z3-engine.js.map +1 -0
  110. package/examples/advanced-features.agentic +98 -0
  111. package/examples/annotations.agentic +37 -0
  112. package/examples/auth.agentic +53 -0
  113. package/examples/enterprise-example.agentic +360 -0
  114. package/examples/minimal.agentic +3 -0
  115. package/examples/minimal.ts +7 -0
  116. package/examples/ml-pipeline.agentic +350 -0
  117. package/examples/multi-agent-example.agentic +212 -0
  118. package/examples/onboarding-tutorial.agentic +263 -0
  119. package/examples/production-api.agentic +304 -0
  120. package/examples/real-world-chatbot.agentic +351 -0
  121. package/examples/result-handling.agentic +34 -0
  122. package/examples/runtime.ts +24 -0
  123. package/examples/showcase.agentic +22 -0
  124. package/examples/showcase.ts +28 -0
  125. package/examples/simple-test.agentic +4 -0
  126. package/examples/simple-test.ts +7 -0
  127. package/examples/simple.agentic +20 -0
  128. package/examples/test2.agentic +4 -0
  129. package/examples/test2.ts +9 -0
  130. package/examples/test3.agentic +4 -0
  131. package/examples/test3.ts +9 -0
  132. package/package.json +70 -0
  133. package/playground/index.html +221 -0
  134. package/playground/playground.js +291 -0
  135. package/registry/package-registry.ts +319 -0
  136. package/scripts/build.js +50 -0
  137. package/scripts/validate-confidence-mutation.ts +112 -0
  138. package/stdlib/async/promise.agentic +216 -0
  139. package/stdlib/database/pool.agentic +235 -0
  140. package/stdlib/file/io.agentic +194 -0
  141. package/stdlib/http/client.agentic +168 -0
  142. package/video-scripts/001-agentic-in-100-seconds.md +175 -0
  143. package/vscode-extension/README.md +67 -0
  144. package/vscode-extension/language-configuration.json +31 -0
  145. package/vscode-extension/package.json +46 -0
  146. package/vscode-extension/syntaxes/agentic.tmLanguage.json +134 -0
@@ -0,0 +1,304 @@
1
+ // Production-Ready REST API Example
2
+ // Demonstrates: error handling, health checks, observability, rate limiting
3
+
4
+ @module("api")
5
+
6
+ // User authentication endpoint
7
+ @confidence(0.93)
8
+ @complete
9
+ @needs(database: Database, jwt: JWTService, logger: Logger)
10
+ @effects(database, io, llm_call)
11
+ @property("rejects empty tokens")
12
+ @property("rejects expired tokens")
13
+ @property("validates token signature")
14
+ func authenticate(token: string) -> Result<User, AuthError> {
15
+ @trace("authentication_start", { tokenLength: token.length })
16
+
17
+ if token.isEmpty() {
18
+ logger.warn("Authentication failed: empty token")
19
+ return Err(AuthError.MISSING_TOKEN)
20
+ }
21
+
22
+ @retry(maxAttempts: 2, backoff: "exponential")
23
+ decoded = jwt.decode(token) match {
24
+ Ok(payload) -> payload,
25
+ Err(error) -> {
26
+ @context {
27
+ what_failed: "JWT decoding",
28
+ suggestions: ["Check token format", "Verify JWT_SECRET", "Check token expiration"],
29
+ recovery: { action: "refresh_token", command: "POST /auth/refresh" }
30
+ }
31
+ logger.error("JWT decode failed", error)
32
+ return Err(AuthError.INVALID_TOKEN)
33
+ }
34
+ }
35
+
36
+ if decoded.exp < now() {
37
+ logger.warn("Authentication failed: token expired")
38
+ return Err(AuthError.EXPIRED_TOKEN)
39
+ }
40
+
41
+ @circuit_breaker(threshold: 5, timeout: 30s)
42
+ user = database.users.find(decoded.userId) match {
43
+ Ok(Some(u)) -> u,
44
+ Ok(None) -> return Err(AuthError.USER_NOT_FOUND),
45
+ Err(e) -> {
46
+ @context {
47
+ what_failed: "User lookup",
48
+ userId: decoded.userId,
49
+ suggestions: ["Check database connection", "Verify user exists"]
50
+ }
51
+ return Err(AuthError.DATABASE_ERROR(e))
52
+ }
53
+ }
54
+
55
+ logger.info("User ${user.id} authenticated successfully")
56
+
57
+ return Ok(user)
58
+ }
59
+
60
+ // Create new user with validation
61
+ @confidence(0.91)
62
+ @complete
63
+ @needs(database: Database, validator: Validator, logger: Logger)
64
+ @effects(database, io)
65
+ @property("rejects invalid emails")
66
+ @property("rejects weak passwords")
67
+ @property("prevents duplicate users")
68
+ @requires_approval(threshold: "high_risk_signup")
69
+ func createUser(email: string, password: string) -> Result<User, CreateUserError> {
70
+ // Validate email
71
+ @confidence(0.95)
72
+ validEmail = validator.validateEmail(email) match {
73
+ Ok(e) -> e,
74
+ Err(e) -> return Err(CreateUserError.INVALID_EMAIL(e))
75
+ }
76
+
77
+ // Validate password strength
78
+ @confidence(0.93)
79
+ @property("enforces minimum 8 characters")
80
+ @property("requires mixed case")
81
+ @property("requires special character")
82
+ validator.validatePassword(password) match {
83
+ Ok(_) -> {},
84
+ Err(e) -> return Err(CreateUserError.WEAK_PASSWORD(e))
85
+ }
86
+
87
+ // Check for duplicates
88
+ existing = database.users.findByEmail(email) match {
89
+ Ok(Some(_)) -> return Err(CreateUserError.EMAIL_ALREADY_EXISTS),
90
+ Ok(None) -> {},
91
+ Err(e) -> return Err(CreateUserError.DATABASE_ERROR(e))
92
+ }
93
+
94
+ // Create user with transaction
95
+ @transaction
96
+ user = database.users.create({
97
+ email: validEmail,
98
+ passwordHash: hash(password),
99
+ createdAt: now()
100
+ }) match {
101
+ Ok(u) -> u,
102
+ Err(e) -> {
103
+ @context {
104
+ what_failed: "User creation",
105
+ email: validEmail,
106
+ suggestions: ["Check database constraints", "Verify unique email"]
107
+ }
108
+ return Err(CreateUserError.CREATE_FAILED(e))
109
+ }
110
+ }
111
+
112
+ logger.info("User created: ${user.id}")
113
+
114
+ return Ok(user)
115
+ }
116
+
117
+ // Health check endpoint
118
+ @healthcheck(interval: 30s)
119
+ @confidence(0.96)
120
+ @effects(database, network)
121
+ func checkAPIHealth() -> HealthStatus {
122
+ checks = [
123
+ checkDatabaseConnection(),
124
+ checkRedisConnection(),
125
+ checkExternalAPIs()
126
+ ]
127
+
128
+ failures = checks.filter(c => c.status == "failed")
129
+
130
+ if failures.length == 0 {
131
+ return HealthStatus.OK
132
+ } else if failures.length < checks.length {
133
+ return HealthStatus.DEGRADED {
134
+ message: "${failures.length} services unhealthy",
135
+ details: failures
136
+ }
137
+ } else {
138
+ return HealthStatus.FAILED {
139
+ message: "All services unhealthy",
140
+ details: failures
141
+ }
142
+ }
143
+ }
144
+
145
+ @recovery(for: checkAPIHealth)
146
+ @confidence(0.84)
147
+ func recoverAPI() -> Result<void, Error> {
148
+ @escalate_to_human("API health critical, human intervention needed")
149
+
150
+ // Attempt reconnections
151
+ database.reconnect()
152
+ redis.reconnect()
153
+
154
+ return Ok(void)
155
+ }
156
+
157
+ // Rate limiting
158
+ @rate_limit(
159
+ window: 1m,
160
+ maxRequests: 100,
161
+ perUser: true,
162
+ action: "reject_with_429"
163
+ )
164
+ @confidence(0.94)
165
+ @effects(database, state)
166
+ func getUser(userId: string, requestingUser: User) -> Result<User, Error> {
167
+ // Automatically rate-limited
168
+ // Returns 429 Too Many Requests if limit exceeded
169
+
170
+ @cache(ttl: 5m, key: "user:${userId}")
171
+ user = database.users.find(userId) match {
172
+ Ok(Some(u)) -> u,
173
+ Ok(None) -> return Err(Error.USER_NOT_FOUND),
174
+ Err(e) -> return Err(Error.DATABASE_ERROR(e))
175
+ }
176
+
177
+ return Ok(user)
178
+ }
179
+
180
+ // List users with pagination
181
+ @confidence(0.92)
182
+ @complete
183
+ @needs(database: Database)
184
+ @effects(database, io)
185
+ @property("respects limit parameter")
186
+ @property("returns empty array when no results")
187
+ @property("handles invalid pagination")
188
+ func listUsers(
189
+ page: number = 1,
190
+ limit: number = 20,
191
+ filter: Option<UserFilter> = None
192
+ ) -> Result<PaginatedResponse<User>, Error> {
193
+ if limit < 1 or limit > 100 {
194
+ return Err(Error.INVALID_LIMIT)
195
+ }
196
+
197
+ if page < 1 {
198
+ return Err(Error.INVALID_PAGE)
199
+ }
200
+
201
+ offset = (page - 1) * limit
202
+
203
+ query = database.users.select()
204
+ .limit(limit)
205
+ .offset(offset)
206
+
207
+ if filter {
208
+ query = query.where("status", "=", filter.status)
209
+ }
210
+
211
+ @circuit_breaker(threshold: 3, timeout: 30s)
212
+ users = query.execute() match {
213
+ Ok(u) -> u,
214
+ Err(e) -> return Err(Error.DATABASE_ERROR(e))
215
+ }
216
+
217
+ total = database.users.count() match {
218
+ Ok(c) -> c,
219
+ Err(e) -> return Err(Error.DATABASE_ERROR(e))
220
+ }
221
+
222
+ return Ok(PaginatedResponse {
223
+ data: users,
224
+ page: page,
225
+ limit: limit,
226
+ total: total,
227
+ totalPages: ceil(total / limit)
228
+ })
229
+ }
230
+
231
+ // Error handling middleware
232
+ @confidence(0.89)
233
+ @effects(io)
234
+ func errorHandler(error: Error, request: Request) -> Response {
235
+ @trace_error(error, {
236
+ path: request.path,
237
+ method: request.method,
238
+ userId: request.user?.id
239
+ })
240
+
241
+ error match {
242
+ AuthError.MISSING_TOKEN -> Response {
243
+ status: 401,
244
+ body: { error: "Missing authentication token" }
245
+ },
246
+ AuthError.EXPIRED_TOKEN -> Response {
247
+ status: 401,
248
+ body: { error: "Token expired", action: "refresh_token" }
249
+ },
250
+ Error.RATE_LIMIT_EXCEEDED -> Response {
251
+ status: 429,
252
+ body: { error: "Too many requests", retryAfter: 60 }
253
+ },
254
+ DatabaseError(_) -> Response {
255
+ status: 503,
256
+ body: { error: "Service temporarily unavailable" }
257
+ },
258
+ _ -> Response {
259
+ status: 500,
260
+ body: { error: "Internal server error", requestId: request.id }
261
+ }
262
+ }
263
+ }
264
+
265
+ // Main API server
266
+ @confidence(0.87)
267
+ @effects(network, database, io)
268
+ @observability(
269
+ tracing: true,
270
+ metrics: true,
271
+ logging: true
272
+ )
273
+ func startServer(port: number) -> Result<void, ServerError> {
274
+ server = createHTTPServer({
275
+ port: port,
276
+ routes: [
277
+ { method: "POST", path: "/auth/login", handler: authenticate },
278
+ { method: "POST", path: "/users", handler: createUser },
279
+ { method: "GET", path: "/users/:id", handler: getUser },
280
+ { method: "GET", path: "/users", handler: listUsers },
281
+ { method: "GET", path: "/health", handler: checkAPIHealth }
282
+ ],
283
+ errorHandler: errorHandler,
284
+ middleware: [
285
+ rateLimitMiddleware,
286
+ authMiddleware,
287
+ loggingMiddleware
288
+ ]
289
+ })
290
+
291
+ @healthcheck(interval: 30s)
292
+ monitorHealth()
293
+
294
+ server.listen() match {
295
+ Ok(_) -> {
296
+ logger.info("API server started on port ${port}")
297
+ return Ok(void)
298
+ },
299
+ Err(e) -> {
300
+ logger.error("Failed to start server", e)
301
+ return Err(ServerError.STARTUP_FAILED(e))
302
+ }
303
+ }
304
+ }
@@ -0,0 +1,351 @@
1
+ // Real-World Example: Production Chatbot with Multi-Agent Coordination
2
+ // Demonstrates: HITL, cost tracking, session persistence, observability
3
+
4
+ @module("chatbot")
5
+
6
+ // Main chatbot agent
7
+ @agent(role: "chatbot", capabilities: ["conversation", "task_routing"])
8
+ agent ChatbotAgent {
9
+ inbox: Channel<UserMessage>
10
+ outbox: Channel<AssistantMessage>
11
+
12
+ @session(storage: "redis", ttl: 24h)
13
+ @budget_limit(user_daily: 5.00, action: "throttle")
14
+ @confidence(0.87)
15
+ func handleMessage(message: UserMessage) -> AssistantMessage {
16
+ @trace_conversation({
17
+ userId: message.userId,
18
+ messageId: message.id,
19
+ intent: classifyIntent(message.text)
20
+ })
21
+
22
+ // Restore session context
23
+ session = Session.restore(message.userId) or {
24
+ session = Session.new(message.userId)
25
+ }
26
+
27
+ // Add to conversation history
28
+ session.addMessage({ role: "user", content: message.text })
29
+
30
+ // Check budget
31
+ budget = costRuntime.checkBudget(message.userId)
32
+ if budget.remaining < 0.10 {
33
+ return AssistantMessage {
34
+ text: "You've reached your daily limit. Upgrade to continue.",
35
+ metadata: { budgetExceeded: true }
36
+ }
37
+ }
38
+
39
+ // Route based on intent
40
+ intent = classifyIntent(message.text)
41
+
42
+ response = intent match {
43
+ "simple_question" -> answerWithCheapModel(message, session),
44
+ "complex_analysis" -> delegateToSpecialist(message, session),
45
+ "sensitive_action" -> requireHumanApproval(message, session),
46
+ _ -> defaultResponse(message, session)
47
+ }
48
+
49
+ // Save session
50
+ session.addMessage({ role: "assistant", content: response.text })
51
+ session.save()
52
+
53
+ return response
54
+ }
55
+ }
56
+
57
+ // Simple questions use cheap model
58
+ @confidence(0.88)
59
+ @cost_optimized(model: "gpt-4.5-turbo")
60
+ @effects(llm_call, cost)
61
+ func answerWithCheapModel(
62
+ message: UserMessage,
63
+ session: Session
64
+ ) -> AssistantMessage {
65
+ @llm_call(
66
+ model: "gpt-4.5-turbo",
67
+ temperature: 0.7,
68
+ max_tokens: 300
69
+ )
70
+ @cost_tracked(
71
+ userId: message.userId,
72
+ feature: "simple_qa",
73
+ model: "gpt-4.5-turbo"
74
+ )
75
+ response = llm.complete({
76
+ system: "You are a helpful assistant. Be concise.",
77
+ messages: session.getRecentMessages(10),
78
+ user: message.text
79
+ })
80
+
81
+ return AssistantMessage {
82
+ text: response.text,
83
+ metadata: {
84
+ model: "gpt-4.5-turbo",
85
+ cost: response.cost,
86
+ confidence: 0.88
87
+ }
88
+ }
89
+ }
90
+
91
+ // Complex questions delegate to specialist agent
92
+ @confidence(0.82)
93
+ @effects(llm_call, cost, async)
94
+ @needs(specialist: SpecialistAgent)
95
+ func delegateToSpecialist(
96
+ message: UserMessage,
97
+ session: Session
98
+ ) -> AssistantMessage {
99
+ @handoff {
100
+ to: "specialist_agent",
101
+ reason: "Complex analysis required",
102
+ context: {
103
+ conversationHistory: session.getAllMessages(),
104
+ intent: "complex_analysis",
105
+ userPreferences: session.getUserPreferences()
106
+ }
107
+ }
108
+
109
+ @timeout(30s)
110
+ response = specialist.inbox.send(SpecialistRequest {
111
+ message: message,
112
+ context: session
113
+ })
114
+
115
+ result = specialist.outbox.receive() match {
116
+ Some(r) -> r,
117
+ None -> {
118
+ // Specialist timed out, use fallback
119
+ return AssistantMessage {
120
+ text: "This is complex. Let me get a human expert to help.",
121
+ metadata: { requiresHuman: true }
122
+ }
123
+ }
124
+ }
125
+
126
+ return AssistantMessage {
127
+ text: result.text,
128
+ metadata: {
129
+ handledBy: "specialist",
130
+ confidence: result.confidence
131
+ }
132
+ }
133
+ }
134
+
135
+ // Sensitive actions require human approval
136
+ @confidence(0.90)
137
+ @requires_approval(
138
+ channel: "slack",
139
+ approvers: ["support_team"],
140
+ timeout: 10m,
141
+ fallback: "reject"
142
+ )
143
+ @effects(human_interaction, io)
144
+ func requireHumanApproval(
145
+ message: UserMessage,
146
+ session: Session
147
+ ) -> AssistantMessage {
148
+ @trace_decision("human_approval_requested", {
149
+ reason: "Sensitive action detected",
150
+ action: classifyAction(message.text),
151
+ userId: message.userId
152
+ })
153
+
154
+ approval = approvalRuntime.requestApproval(
155
+ "User requesting: ${message.text}",
156
+ {
157
+ userId: message.userId,
158
+ conversationHistory: session.getRecentMessages(5),
159
+ riskLevel: assessRisk(message)
160
+ },
161
+ {
162
+ channel: "slack",
163
+ approvers: ["support_team"],
164
+ timeout: 10 * 60 * 1000, // 10 minutes
165
+ fallback: "reject"
166
+ }
167
+ ) match {
168
+ Ok({ approved: true, reason }) -> {
169
+ // Approved - proceed with action
170
+ return executeApprovedAction(message, session, reason)
171
+ },
172
+ Ok({ approved: false, reason }) -> {
173
+ // Rejected
174
+ return AssistantMessage {
175
+ text: "I cannot complete that action. Reason: ${reason}",
176
+ metadata: { approved: false }
177
+ }
178
+ },
179
+ Err(e) -> {
180
+ // Approval system failed
181
+ return AssistantMessage {
182
+ text: "Unable to get approval. Please try again later.",
183
+ metadata: { error: e }
184
+ }
185
+ }
186
+ }
187
+ }
188
+
189
+ // Specialist agent for complex queries
190
+ @agent(role: "specialist", capabilities: ["deep_analysis", "research"])
191
+ agent SpecialistAgent {
192
+ inbox: Channel<SpecialistRequest>
193
+ outbox: Channel<SpecialistResponse>
194
+
195
+ @handler("specialist_request")
196
+ @confidence(0.85)
197
+ @effects(llm_call, network, cost)
198
+ func handleRequest(request: SpecialistRequest) -> SpecialistResponse {
199
+ // Use more powerful model
200
+ @llm_call(
201
+ model: "gpt-4.5",
202
+ temperature: 0.8,
203
+ max_tokens: 1000
204
+ )
205
+ @cost_tracked(
206
+ userId: request.message.userId,
207
+ feature: "specialist_analysis",
208
+ model: "gpt-4.5"
209
+ )
210
+ analysis = llm.complete({
211
+ system: "You are an expert analyst. Provide detailed, accurate analysis.",
212
+ messages: request.context.getAllMessages(),
213
+ user: request.message.text
214
+ })
215
+
216
+ // If still uncertain, use ensemble
217
+ if analysis.confidence < 0.75 {
218
+ @ensemble([
219
+ llm("gpt-4.5"),
220
+ llm("claude-sonnet-4-5"),
221
+ llm("gemini-2.0-pro")
222
+ ])
223
+ analysis = ensembleAnalysis(request)
224
+ }
225
+
226
+ return SpecialistResponse {
227
+ text: analysis.text,
228
+ confidence: analysis.confidence,
229
+ sources: analysis.sources,
230
+ timestamp: now()
231
+ }
232
+ }
233
+ }
234
+
235
+ // Input guardrails for safety
236
+ @input_guardrails(
237
+ pii_detection: true,
238
+ prompt_injection: true,
239
+ toxicity_threshold: 0.8,
240
+ action: "reject"
241
+ )
242
+ @confidence(0.94)
243
+ func validateUserInput(text: string) -> Result<string, ValidationError> {
244
+ // Automatic validation before processing
245
+ // Checks for: PII, prompt injection, toxicity, etc.
246
+
247
+ validated = InputGuard.check(text)
248
+
249
+ if validated.has_pii {
250
+ @audit_security("pii_detected", { userId, inputHash: hash(text) })
251
+ return Err(ValidationError.PII_DETECTED)
252
+ }
253
+
254
+ if validated.injection_score > 0.7 {
255
+ @audit_security("injection_attempt", { score: validated.injection_score })
256
+ return Err(ValidationError.INJECTION_ATTEMPT)
257
+ }
258
+
259
+ if validated.toxicity > 0.8 {
260
+ return Err(ValidationError.TOXIC_CONTENT)
261
+ }
262
+
263
+ return Ok(validated.sanitized)
264
+ }
265
+
266
+ // Output guardrails
267
+ @output_guardrails(
268
+ checks: ["toxicity", "bias", "pii", "factuality"],
269
+ enforcement: "block",
270
+ fallback: "I cannot provide that information."
271
+ )
272
+ @confidence(0.92)
273
+ func validateAssistantOutput(text: string) -> Result<string, ValidationError> {
274
+ // Automatic output validation
275
+ // Ensures responses are safe, unbiased, and factual
276
+ }
277
+
278
+ // Health monitoring
279
+ @healthcheck(interval: 30s)
280
+ @confidence(0.95)
281
+ func checkChatbotHealth() -> HealthStatus {
282
+ checks = [
283
+ database.ping(),
284
+ redis.ping(),
285
+ llmAPI.ping()
286
+ ]
287
+
288
+ allHealthy = checks.all(c => c == HealthStatus.OK)
289
+
290
+ return allHealthy ? HealthStatus.OK : HealthStatus.DEGRADED
291
+ }
292
+
293
+ // Cost analytics
294
+ @confidence(0.93)
295
+ func generateCostReport(userId: string, period: Period) -> CostReport {
296
+ costs = costRuntime.getReport({
297
+ userId: userId,
298
+ period: period,
299
+ groupBy: ["feature", "model"]
300
+ })
301
+
302
+ return CostReport {
303
+ totalCost: costs.total,
304
+ breakdown: costs.byFeature,
305
+ topModels: costs.byModel,
306
+ recommendations: generateCostOptimizations(costs)
307
+ }
308
+ }
309
+
310
+ // Main entry point
311
+ @confidence(0.89)
312
+ @observable(tracing: true, metrics: true, logging: true)
313
+ @effects(network, database, llm_call, io, cost, human_interaction)
314
+ func runChatbot(port: number) -> Result<void, Error> {
315
+ // Initialize agents
316
+ chatbot = spawn ChatbotAgent()
317
+ specialist = spawn SpecialistAgent()
318
+
319
+ // Start health monitoring
320
+ @background
321
+ monitorHealth()
322
+
323
+ // Start HTTP server
324
+ server = createServer({
325
+ port: port,
326
+ routes: [
327
+ { method: "POST", path: "/chat", handler: chatbot.handleMessage },
328
+ { method: "GET", path: "/health", handler: checkChatbotHealth },
329
+ { method: "GET", path: "/costs", handler: generateCostReport }
330
+ ]
331
+ })
332
+
333
+ server.listen()
334
+
335
+ logger.info("🤖 Chatbot started on port ${port}")
336
+
337
+ return Ok(void)
338
+ }
339
+ ```
340
+
341
+ This is a **production-ready chatbot** with:
342
+ - Multi-agent coordination
343
+ - Cost tracking and budgets
344
+ - Safety guardrails (input + output)
345
+ - Human-in-the-loop for sensitive actions
346
+ - Session persistence
347
+ - Health monitoring
348
+ - Observability (tracing, metrics, logging)
349
+ - Ensemble models for high-stakes queries
350
+
351
+ **Try building this in another language - it's 3-5x more code!**
@@ -0,0 +1,34 @@
1
+ // Example: Result type handling in Agentic
2
+ // Demonstrates pattern matching with Ok/Err
3
+
4
+ @confidence(0.95, "Production ready")
5
+ @complete
6
+ func divide(a: number, b: number) -> Result<number, string> {
7
+ if b == 0 {
8
+ return Err("Division by zero")
9
+ }
10
+ return Ok(a / b)
11
+ }
12
+
13
+ @confidence(0.92, "Well tested")
14
+ @complete
15
+ func safeDivide(a: number, b: number) -> number {
16
+ divide(a, b) match {
17
+ Ok(result) -> return result,
18
+ Err(error) -> return 0
19
+ }
20
+ }
21
+
22
+ @partial
23
+ @confidence(0.75, "Basic implementation")
24
+ func chainedCalculation(x: number, y: number) -> Result<number, string> {
25
+ divide(x, 2) match {
26
+ Ok(half) -> {
27
+ divide(half, y) match {
28
+ Ok(final) -> return Ok(final),
29
+ Err(e) -> return Err(e)
30
+ }
31
+ },
32
+ Err(e) -> return Err(e)
33
+ }
34
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Runtime stub for examples
3
+ * In production, this would be @agentic/runtime npm package
4
+ */
5
+
6
+ export type Result<T, E> = { ok: true; value: T } | { ok: false; error: E };
7
+
8
+ export function Ok<T>(value: T): Result<T, never> {
9
+ return { ok: true, value };
10
+ }
11
+
12
+ export function Err<E>(error: E): Result<never, E> {
13
+ return { ok: false, error };
14
+ }
15
+
16
+ export class AgenticRuntime {
17
+ static confidence = {
18
+ register: (name: string, level: number, reason?: string) => {
19
+ if (level < 0.80) {
20
+ console.warn(`⚠️ Low confidence (${level}) in ${name}`);
21
+ }
22
+ }
23
+ };
24
+ }