agent-messenger 1.0.0 → 1.1.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 (330) hide show
  1. package/.claude/commands/release.md +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.github/workflows/ci.yml +1 -1
  4. package/.github/workflows/e2e.yml.disabled +69 -0
  5. package/README.md +16 -14
  6. package/biome.json +33 -1
  7. package/bun.lock +63 -0
  8. package/dist/package.json +8 -4
  9. package/dist/src/cli.d.ts.map +1 -1
  10. package/dist/src/cli.js +4 -1
  11. package/dist/src/cli.js.map +1 -1
  12. package/dist/src/platforms/discord/cli.js +1 -1
  13. package/dist/src/platforms/discord/client.d.ts.map +1 -1
  14. package/dist/src/platforms/discord/client.js +3 -3
  15. package/dist/src/platforms/discord/client.js.map +1 -1
  16. package/dist/src/platforms/discord/commands/user.d.ts.map +1 -1
  17. package/dist/src/platforms/discord/commands/user.js +10 -1
  18. package/dist/src/platforms/discord/commands/user.js.map +1 -1
  19. package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -1
  20. package/dist/src/platforms/discord/credential-manager.js +18 -12
  21. package/dist/src/platforms/discord/credential-manager.js.map +1 -1
  22. package/dist/src/platforms/slack/cli.js +1 -1
  23. package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -1
  24. package/dist/src/platforms/slack/credential-manager.js +20 -6
  25. package/dist/src/platforms/slack/credential-manager.js.map +1 -1
  26. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  27. package/dist/src/platforms/slack/token-extractor.js +34 -9
  28. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  29. package/dist/src/platforms/teams/cli.d.ts.map +1 -0
  30. package/dist/{cli.js → src/platforms/teams/cli.js} +11 -10
  31. package/dist/src/platforms/teams/cli.js.map +1 -0
  32. package/dist/src/platforms/teams/client.d.ts +32 -0
  33. package/dist/src/platforms/teams/client.d.ts.map +1 -0
  34. package/dist/src/platforms/teams/client.js +202 -0
  35. package/dist/src/platforms/teams/client.js.map +1 -0
  36. package/dist/src/platforms/teams/commands/auth.d.ts +14 -0
  37. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -0
  38. package/dist/src/platforms/teams/commands/auth.js +176 -0
  39. package/dist/src/platforms/teams/commands/auth.js.map +1 -0
  40. package/dist/src/platforms/teams/commands/channel.d.ts +13 -0
  41. package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -0
  42. package/dist/src/platforms/teams/commands/channel.js +97 -0
  43. package/dist/src/platforms/teams/commands/channel.js.map +1 -0
  44. package/dist/src/platforms/teams/commands/file.d.ts +12 -0
  45. package/dist/src/platforms/teams/commands/file.d.ts.map +1 -0
  46. package/dist/src/platforms/teams/commands/file.js +104 -0
  47. package/dist/src/platforms/teams/commands/file.js.map +1 -0
  48. package/dist/{commands → src/platforms/teams/commands}/index.d.ts +5 -2
  49. package/dist/src/platforms/teams/commands/index.d.ts.map +1 -0
  50. package/dist/{commands → src/platforms/teams/commands}/index.js +5 -2
  51. package/dist/src/platforms/teams/commands/index.js.map +1 -0
  52. package/dist/src/platforms/teams/commands/message.d.ts +17 -0
  53. package/dist/src/platforms/teams/commands/message.d.ts.map +1 -0
  54. package/dist/src/platforms/teams/commands/message.js +133 -0
  55. package/dist/src/platforms/teams/commands/message.js.map +1 -0
  56. package/dist/src/platforms/teams/commands/reaction.d.ts +9 -0
  57. package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -0
  58. package/dist/src/platforms/teams/commands/reaction.js +68 -0
  59. package/dist/src/platforms/teams/commands/reaction.js.map +1 -0
  60. package/dist/src/platforms/teams/commands/snapshot.d.ts +10 -0
  61. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -0
  62. package/dist/src/platforms/teams/commands/snapshot.js +85 -0
  63. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -0
  64. package/dist/src/platforms/teams/commands/team.d.ts +18 -0
  65. package/dist/src/platforms/teams/commands/team.d.ts.map +1 -0
  66. package/dist/src/platforms/teams/commands/team.js +130 -0
  67. package/dist/src/platforms/teams/commands/team.js.map +1 -0
  68. package/dist/src/platforms/teams/commands/user.d.ts.map +1 -0
  69. package/dist/src/platforms/teams/commands/user.js +88 -0
  70. package/dist/src/platforms/teams/commands/user.js.map +1 -0
  71. package/dist/src/platforms/teams/credential-manager.d.ts +18 -0
  72. package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -0
  73. package/dist/src/platforms/teams/credential-manager.js +81 -0
  74. package/dist/src/platforms/teams/credential-manager.js.map +1 -0
  75. package/dist/src/platforms/teams/index.d.ts +4 -0
  76. package/dist/src/platforms/teams/index.d.ts.map +1 -0
  77. package/dist/src/platforms/teams/index.js +6 -0
  78. package/dist/src/platforms/teams/index.js.map +1 -0
  79. package/dist/src/platforms/teams/token-extractor.d.ts +36 -0
  80. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -0
  81. package/dist/src/platforms/teams/token-extractor.js +335 -0
  82. package/dist/src/platforms/teams/token-extractor.js.map +1 -0
  83. package/dist/src/platforms/teams/types.d.ts +209 -0
  84. package/dist/src/platforms/teams/types.d.ts.map +1 -0
  85. package/dist/src/platforms/teams/types.js +65 -0
  86. package/dist/src/platforms/teams/types.js.map +1 -0
  87. package/docs/teams.md +321 -0
  88. package/e2e/README.md +256 -0
  89. package/e2e/config.ts +45 -0
  90. package/e2e/discord.e2e.test.ts +252 -0
  91. package/e2e/helpers.ts +107 -0
  92. package/e2e/slack.e2e.test.ts +309 -0
  93. package/package.json +8 -4
  94. package/scripts/postbuild.ts +15 -0
  95. package/skills/agent-teams/SKILL.md +292 -0
  96. package/skills/agent-teams/references/authentication.md +375 -0
  97. package/skills/agent-teams/references/common-patterns.md +596 -0
  98. package/skills/agent-teams/templates/monitor-channel.sh +239 -0
  99. package/skills/agent-teams/templates/post-message.sh +224 -0
  100. package/skills/agent-teams/templates/team-summary.sh +210 -0
  101. package/src/cli.ts +4 -0
  102. package/src/platforms/discord/client.ts +3 -3
  103. package/src/platforms/discord/commands/auth.test.ts +48 -32
  104. package/src/platforms/discord/commands/channel.test.ts +54 -42
  105. package/src/platforms/discord/commands/file.test.ts +40 -53
  106. package/src/platforms/discord/commands/guild.test.ts +47 -27
  107. package/src/platforms/discord/commands/message.test.ts +54 -51
  108. package/src/platforms/discord/commands/reaction.test.ts +54 -42
  109. package/src/platforms/discord/commands/user.ts +12 -1
  110. package/src/platforms/discord/credential-manager.test.ts +137 -136
  111. package/src/platforms/discord/credential-manager.ts +20 -13
  112. package/src/platforms/discord/token-extractor.test.ts +133 -383
  113. package/{tests → src/platforms/slack}/cli.test.ts +3 -3
  114. package/{tests/slack-client.test.ts → src/platforms/slack/client.test.ts} +1 -1
  115. package/{tests → src/platforms/slack}/commands/auth.test.ts +25 -13
  116. package/{tests → src/platforms/slack}/commands/channel.test.ts +2 -2
  117. package/{tests → src/platforms/slack}/commands/file.test.ts +2 -2
  118. package/{tests → src/platforms/slack}/commands/message.test.ts +2 -2
  119. package/{tests → src/platforms/slack}/commands/reaction.test.ts +1 -1
  120. package/{tests → src/platforms/slack}/commands/snapshot.test.ts +117 -105
  121. package/{tests → src/platforms/slack}/commands/user.test.ts +3 -3
  122. package/{tests → src/platforms/slack}/commands/workspace.test.ts +44 -95
  123. package/{tests → src/platforms/slack}/credential-manager.test.ts +2 -2
  124. package/src/platforms/slack/credential-manager.ts +22 -7
  125. package/src/platforms/slack/token-extractor-node-test.ts +40 -0
  126. package/src/platforms/slack/token-extractor-node.test.ts +10 -0
  127. package/src/platforms/slack/token-extractor.ts +36 -10
  128. package/{tests → src/platforms/slack}/types.test.ts +1 -1
  129. package/src/platforms/teams/cli.ts +36 -0
  130. package/src/platforms/teams/client.test.ts +500 -0
  131. package/src/platforms/teams/client.ts +365 -0
  132. package/src/platforms/teams/commands/auth.test.ts +99 -0
  133. package/src/platforms/teams/commands/auth.ts +232 -0
  134. package/src/platforms/teams/commands/channel.test.ts +147 -0
  135. package/src/platforms/teams/commands/channel.ts +129 -0
  136. package/src/platforms/teams/commands/file.test.ts +88 -0
  137. package/src/platforms/teams/commands/file.ts +144 -0
  138. package/src/platforms/teams/commands/index.ts +12 -0
  139. package/src/platforms/teams/commands/message.test.ts +110 -0
  140. package/src/platforms/teams/commands/message.ts +188 -0
  141. package/src/platforms/teams/commands/reaction.test.ts +87 -0
  142. package/src/platforms/teams/commands/reaction.ts +104 -0
  143. package/src/platforms/teams/commands/snapshot.test.ts +35 -0
  144. package/src/platforms/teams/commands/snapshot.ts +115 -0
  145. package/src/platforms/teams/commands/team.test.ts +157 -0
  146. package/src/platforms/teams/commands/team.ts +164 -0
  147. package/src/platforms/teams/commands/user.test.ts +83 -0
  148. package/src/platforms/teams/commands/user.ts +112 -0
  149. package/src/platforms/teams/credential-manager.test.ts +178 -0
  150. package/src/platforms/teams/credential-manager.ts +92 -0
  151. package/src/platforms/teams/index.ts +5 -0
  152. package/src/platforms/teams/token-extractor.test.ts +429 -0
  153. package/src/platforms/teams/token-extractor.ts +462 -0
  154. package/src/platforms/teams/types.test.ts +226 -0
  155. package/src/platforms/teams/types.ts +140 -0
  156. package/tsconfig.json +1 -1
  157. package/dist/cli.d.ts.map +0 -1
  158. package/dist/cli.js.map +0 -1
  159. package/dist/commands/auth.d.ts +0 -3
  160. package/dist/commands/auth.d.ts.map +0 -1
  161. package/dist/commands/auth.js +0 -140
  162. package/dist/commands/auth.js.map +0 -1
  163. package/dist/commands/channel.d.ts +0 -3
  164. package/dist/commands/channel.d.ts.map +0 -1
  165. package/dist/commands/channel.js +0 -118
  166. package/dist/commands/channel.js.map +0 -1
  167. package/dist/commands/file.d.ts +0 -3
  168. package/dist/commands/file.d.ts.map +0 -1
  169. package/dist/commands/file.js +0 -113
  170. package/dist/commands/file.js.map +0 -1
  171. package/dist/commands/index.d.ts.map +0 -1
  172. package/dist/commands/index.js.map +0 -1
  173. package/dist/commands/message.d.ts +0 -3
  174. package/dist/commands/message.d.ts.map +0 -1
  175. package/dist/commands/message.js +0 -214
  176. package/dist/commands/message.js.map +0 -1
  177. package/dist/commands/reaction.d.ts +0 -3
  178. package/dist/commands/reaction.d.ts.map +0 -1
  179. package/dist/commands/reaction.js +0 -100
  180. package/dist/commands/reaction.js.map +0 -1
  181. package/dist/commands/snapshot.d.ts +0 -3
  182. package/dist/commands/snapshot.d.ts.map +0 -1
  183. package/dist/commands/snapshot.js +0 -88
  184. package/dist/commands/snapshot.js.map +0 -1
  185. package/dist/commands/user.d.ts.map +0 -1
  186. package/dist/commands/user.js +0 -96
  187. package/dist/commands/user.js.map +0 -1
  188. package/dist/commands/workspace.d.ts +0 -3
  189. package/dist/commands/workspace.d.ts.map +0 -1
  190. package/dist/commands/workspace.js +0 -89
  191. package/dist/commands/workspace.js.map +0 -1
  192. package/dist/lib/credential-manager.d.ts +0 -13
  193. package/dist/lib/credential-manager.d.ts.map +0 -1
  194. package/dist/lib/credential-manager.js +0 -58
  195. package/dist/lib/credential-manager.js.map +0 -1
  196. package/dist/lib/index.d.ts +0 -3
  197. package/dist/lib/index.d.ts.map +0 -1
  198. package/dist/lib/index.js +0 -3
  199. package/dist/lib/index.js.map +0 -1
  200. package/dist/lib/ref-manager.d.ts +0 -26
  201. package/dist/lib/ref-manager.d.ts.map +0 -1
  202. package/dist/lib/ref-manager.js +0 -92
  203. package/dist/lib/ref-manager.js.map +0 -1
  204. package/dist/lib/slack-client.d.ts +0 -37
  205. package/dist/lib/slack-client.d.ts.map +0 -1
  206. package/dist/lib/slack-client.js +0 -379
  207. package/dist/lib/slack-client.js.map +0 -1
  208. package/dist/lib/token-extractor.d.ts +0 -28
  209. package/dist/lib/token-extractor.d.ts.map +0 -1
  210. package/dist/lib/token-extractor.js +0 -401
  211. package/dist/lib/token-extractor.js.map +0 -1
  212. package/dist/src/platforms/discord/client.test.d.ts +0 -2
  213. package/dist/src/platforms/discord/client.test.d.ts.map +0 -1
  214. package/dist/src/platforms/discord/client.test.js +0 -367
  215. package/dist/src/platforms/discord/client.test.js.map +0 -1
  216. package/dist/src/platforms/discord/commands/auth.test.d.ts +0 -2
  217. package/dist/src/platforms/discord/commands/auth.test.d.ts.map +0 -1
  218. package/dist/src/platforms/discord/commands/auth.test.js +0 -65
  219. package/dist/src/platforms/discord/commands/auth.test.js.map +0 -1
  220. package/dist/src/platforms/discord/commands/channel.test.d.ts +0 -2
  221. package/dist/src/platforms/discord/commands/channel.test.d.ts.map +0 -1
  222. package/dist/src/platforms/discord/commands/channel.test.js +0 -136
  223. package/dist/src/platforms/discord/commands/channel.test.js.map +0 -1
  224. package/dist/src/platforms/discord/commands/file.test.d.ts +0 -2
  225. package/dist/src/platforms/discord/commands/file.test.d.ts.map +0 -1
  226. package/dist/src/platforms/discord/commands/file.test.js +0 -83
  227. package/dist/src/platforms/discord/commands/file.test.js.map +0 -1
  228. package/dist/src/platforms/discord/commands/guild.test.d.ts +0 -2
  229. package/dist/src/platforms/discord/commands/guild.test.d.ts.map +0 -1
  230. package/dist/src/platforms/discord/commands/guild.test.js +0 -100
  231. package/dist/src/platforms/discord/commands/guild.test.js.map +0 -1
  232. package/dist/src/platforms/discord/commands/message.test.d.ts +0 -2
  233. package/dist/src/platforms/discord/commands/message.test.d.ts.map +0 -1
  234. package/dist/src/platforms/discord/commands/message.test.js +0 -91
  235. package/dist/src/platforms/discord/commands/message.test.js.map +0 -1
  236. package/dist/src/platforms/discord/commands/reaction.test.d.ts +0 -2
  237. package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +0 -1
  238. package/dist/src/platforms/discord/commands/reaction.test.js +0 -115
  239. package/dist/src/platforms/discord/commands/reaction.test.js.map +0 -1
  240. package/dist/src/platforms/discord/commands/snapshot.test.d.ts +0 -2
  241. package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +0 -1
  242. package/dist/src/platforms/discord/commands/snapshot.test.js +0 -25
  243. package/dist/src/platforms/discord/commands/snapshot.test.js.map +0 -1
  244. package/dist/src/platforms/discord/commands/user.test.d.ts +0 -2
  245. package/dist/src/platforms/discord/commands/user.test.d.ts.map +0 -1
  246. package/dist/src/platforms/discord/commands/user.test.js +0 -103
  247. package/dist/src/platforms/discord/commands/user.test.js.map +0 -1
  248. package/dist/src/platforms/discord/credential-manager.test.d.ts +0 -2
  249. package/dist/src/platforms/discord/credential-manager.test.d.ts.map +0 -1
  250. package/dist/src/platforms/discord/credential-manager.test.js +0 -136
  251. package/dist/src/platforms/discord/credential-manager.test.js.map +0 -1
  252. package/dist/src/platforms/discord/token-extractor.test.d.ts +0 -2
  253. package/dist/src/platforms/discord/token-extractor.test.d.ts.map +0 -1
  254. package/dist/src/platforms/discord/token-extractor.test.js +0 -789
  255. package/dist/src/platforms/discord/token-extractor.test.js.map +0 -1
  256. package/dist/src/platforms/discord/types.test.d.ts +0 -2
  257. package/dist/src/platforms/discord/types.test.d.ts.map +0 -1
  258. package/dist/src/platforms/discord/types.test.js +0 -211
  259. package/dist/src/platforms/discord/types.test.js.map +0 -1
  260. package/dist/src/shared/utils/concurrency.test.d.ts +0 -2
  261. package/dist/src/shared/utils/concurrency.test.d.ts.map +0 -1
  262. package/dist/src/shared/utils/concurrency.test.js +0 -39
  263. package/dist/src/shared/utils/concurrency.test.js.map +0 -1
  264. package/dist/tests/cli.test.d.ts +0 -2
  265. package/dist/tests/cli.test.d.ts.map +0 -1
  266. package/dist/tests/cli.test.js +0 -83
  267. package/dist/tests/cli.test.js.map +0 -1
  268. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +0 -1
  269. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
  270. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +0 -3
  271. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +0 -1
  272. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
  273. package/dist/tests/commands/auth.test.d.ts +0 -2
  274. package/dist/tests/commands/auth.test.d.ts.map +0 -1
  275. package/dist/tests/commands/auth.test.js +0 -304
  276. package/dist/tests/commands/auth.test.js.map +0 -1
  277. package/dist/tests/commands/channel.test.d.ts +0 -2
  278. package/dist/tests/commands/channel.test.d.ts.map +0 -1
  279. package/dist/tests/commands/channel.test.js +0 -166
  280. package/dist/tests/commands/channel.test.js.map +0 -1
  281. package/dist/tests/commands/file.test.d.ts +0 -2
  282. package/dist/tests/commands/file.test.d.ts.map +0 -1
  283. package/dist/tests/commands/file.test.js +0 -175
  284. package/dist/tests/commands/file.test.js.map +0 -1
  285. package/dist/tests/commands/message.test.d.ts +0 -2
  286. package/dist/tests/commands/message.test.d.ts.map +0 -1
  287. package/dist/tests/commands/message.test.js +0 -293
  288. package/dist/tests/commands/message.test.js.map +0 -1
  289. package/dist/tests/commands/reaction.test.d.ts +0 -2
  290. package/dist/tests/commands/reaction.test.d.ts.map +0 -1
  291. package/dist/tests/commands/reaction.test.js +0 -84
  292. package/dist/tests/commands/reaction.test.js.map +0 -1
  293. package/dist/tests/commands/snapshot.test.d.ts +0 -2
  294. package/dist/tests/commands/snapshot.test.d.ts.map +0 -1
  295. package/dist/tests/commands/snapshot.test.js +0 -280
  296. package/dist/tests/commands/snapshot.test.js.map +0 -1
  297. package/dist/tests/commands/user.test.d.ts +0 -2
  298. package/dist/tests/commands/user.test.d.ts.map +0 -1
  299. package/dist/tests/commands/user.test.js +0 -117
  300. package/dist/tests/commands/user.test.js.map +0 -1
  301. package/dist/tests/commands/workspace.test.d.ts +0 -2
  302. package/dist/tests/commands/workspace.test.d.ts.map +0 -1
  303. package/dist/tests/commands/workspace.test.js +0 -453
  304. package/dist/tests/commands/workspace.test.js.map +0 -1
  305. package/dist/tests/credential-manager.test.d.ts +0 -2
  306. package/dist/tests/credential-manager.test.d.ts.map +0 -1
  307. package/dist/tests/credential-manager.test.js +0 -199
  308. package/dist/tests/credential-manager.test.js.map +0 -1
  309. package/dist/tests/slack-client.test.d.ts +0 -2
  310. package/dist/tests/slack-client.test.d.ts.map +0 -1
  311. package/dist/tests/slack-client.test.js +0 -741
  312. package/dist/tests/slack-client.test.js.map +0 -1
  313. package/dist/tests/types.test.d.ts +0 -2
  314. package/dist/tests/types.test.d.ts.map +0 -1
  315. package/dist/tests/types.test.js +0 -215
  316. package/dist/tests/types.test.js.map +0 -1
  317. package/dist/types/index.d.ts +0 -369
  318. package/dist/types/index.d.ts.map +0 -1
  319. package/dist/types/index.js +0 -92
  320. package/dist/types/index.js.map +0 -1
  321. package/dist/utils/error-handler.d.ts +0 -2
  322. package/dist/utils/error-handler.d.ts.map +0 -1
  323. package/dist/utils/error-handler.js +0 -5
  324. package/dist/utils/error-handler.js.map +0 -1
  325. package/dist/utils/output.d.ts +0 -2
  326. package/dist/utils/output.d.ts.map +0 -1
  327. package/dist/utils/output.js +0 -4
  328. package/dist/utils/output.js.map +0 -1
  329. /package/dist/{cli.d.ts → src/platforms/teams/cli.d.ts} +0 -0
  330. /package/dist/{commands → src/platforms/teams/commands}/user.d.ts +0 -0
@@ -0,0 +1,596 @@
1
+ # Common Patterns
2
+
3
+ ## Overview
4
+
5
+ This guide covers typical workflows for AI agents interacting with Microsoft Teams using agent-teams.
6
+
7
+ **Important**: Teams uses UUID-style channel IDs (like `19:abc123@thread.tacv2`). You cannot use channel names directly - always get IDs from `channel list` first.
8
+
9
+ **CRITICAL**: Teams tokens expire in 60-90 minutes! All patterns include token refresh handling.
10
+
11
+ ## Pattern 1: Send a Simple Message
12
+
13
+ **Use case**: Post a notification or update to a channel
14
+
15
+ ```bash
16
+ #!/bin/bash
17
+
18
+ # First, ensure token is valid
19
+ agent-teams auth extract 2>/dev/null || true
20
+
21
+ # Get channel ID from channel list
22
+ CHANNELS=$(agent-teams channel list)
23
+ CHANNEL_ID=$(echo "$CHANNELS" | jq -r '.[] | select(.name=="General") | .id')
24
+
25
+ # Send message using channel ID
26
+ agent-teams message send "$CHANNEL_ID" "Deployment completed successfully!"
27
+
28
+ # With error handling
29
+ RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello world")
30
+ if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
31
+ echo "Message sent!"
32
+ else
33
+ ERROR=$(echo "$RESULT" | jq -r '.error')
34
+
35
+ # Handle token expiry
36
+ if echo "$ERROR" | grep -qi "expired\|401"; then
37
+ echo "Token expired, refreshing..."
38
+ agent-teams auth extract
39
+ agent-teams message send "$CHANNEL_ID" "Hello world"
40
+ else
41
+ echo "Failed: $ERROR"
42
+ exit 1
43
+ fi
44
+ fi
45
+ ```
46
+
47
+ **When to use**: Simple one-off messages after looking up the channel ID.
48
+
49
+ ## Pattern 2: Monitor Channel for New Messages (with Token Refresh)
50
+
51
+ **Use case**: Watch a channel and respond to new messages
52
+
53
+ ```bash
54
+ #!/bin/bash
55
+
56
+ CHANNEL_ID="19:abc123@thread.tacv2"
57
+ LAST_ID=""
58
+ TOKEN_CHECK_INTERVAL=300 # Check token every 5 minutes
59
+
60
+ last_token_check=$(date +%s)
61
+
62
+ refresh_token_if_needed() {
63
+ local now=$(date +%s)
64
+ local elapsed=$((now - last_token_check))
65
+
66
+ if [ $elapsed -gt $TOKEN_CHECK_INTERVAL ]; then
67
+ STATUS=$(agent-teams auth status)
68
+ EXPIRES_SOON=$(echo "$STATUS" | jq -r '.token_expires_soon // true')
69
+
70
+ if [ "$EXPIRES_SOON" = "true" ]; then
71
+ echo "Token expiring soon, refreshing..."
72
+ agent-teams auth extract
73
+ fi
74
+
75
+ last_token_check=$now
76
+ fi
77
+ }
78
+
79
+ while true; do
80
+ # Proactively refresh token
81
+ refresh_token_if_needed
82
+
83
+ # Get latest message
84
+ MESSAGES=$(agent-teams message list "$CHANNEL_ID" --limit 1)
85
+
86
+ # Handle token expiry error
87
+ if echo "$MESSAGES" | jq -e '.error' | grep -qi "expired\|401" 2>/dev/null; then
88
+ echo "Token expired, refreshing..."
89
+ agent-teams auth extract
90
+ continue
91
+ fi
92
+
93
+ LATEST_ID=$(echo "$MESSAGES" | jq -r '.[0].id // ""')
94
+
95
+ # Check if new message
96
+ if [ "$LATEST_ID" != "$LAST_ID" ] && [ -n "$LAST_ID" ]; then
97
+ CONTENT=$(echo "$MESSAGES" | jq -r '.[0].content')
98
+ AUTHOR=$(echo "$MESSAGES" | jq -r '.[0].author')
99
+
100
+ echo "New message from $AUTHOR: $CONTENT"
101
+
102
+ # Process message here
103
+ if echo "$CONTENT" | grep -q "bot"; then
104
+ agent-teams message send "$CHANNEL_ID" "You called?"
105
+ fi
106
+ fi
107
+
108
+ LAST_ID="$LATEST_ID"
109
+ sleep 5
110
+ done
111
+ ```
112
+
113
+ **When to use**: Building a simple bot that reacts to messages.
114
+
115
+ **Limitations**: Polling-based, not real-time. Token must be refreshed every 60-90 minutes.
116
+
117
+ ## Pattern 3: Get Team Overview
118
+
119
+ **Use case**: Understand team state before taking action
120
+
121
+ ```bash
122
+ #!/bin/bash
123
+
124
+ # Ensure fresh token
125
+ agent-teams auth extract 2>/dev/null || true
126
+
127
+ # Get full snapshot
128
+ SNAPSHOT=$(agent-teams snapshot)
129
+
130
+ # Extract key information
131
+ TEAM_NAME=$(echo "$SNAPSHOT" | jq -r '.team.name // "Unknown"')
132
+ CHANNEL_COUNT=$(echo "$SNAPSHOT" | jq -r '.channels | length')
133
+ MEMBER_COUNT=$(echo "$SNAPSHOT" | jq -r '.members | length')
134
+
135
+ echo "Team: $TEAM_NAME"
136
+ echo "Channels: $CHANNEL_COUNT"
137
+ echo "Members: $MEMBER_COUNT"
138
+
139
+ # List all channels
140
+ echo -e "\nChannels:"
141
+ echo "$SNAPSHOT" | jq -r '.channels[] | " #\(.name) (\(.id))"'
142
+
143
+ # List recent activity
144
+ echo -e "\nRecent messages:"
145
+ echo "$SNAPSHOT" | jq -r '.recent_messages[] | " [\(.channel_name)] \(.author): \(.content[0:50])"'
146
+ ```
147
+
148
+ **When to use**: Initial context gathering, status reports, team summaries.
149
+
150
+ ## Pattern 4: Find Channel by Name
151
+
152
+ **Use case**: Get channel ID from channel name
153
+
154
+ ```bash
155
+ #!/bin/bash
156
+
157
+ get_channel_id() {
158
+ local channel_name=$1
159
+
160
+ CHANNELS=$(agent-teams channel list)
161
+ CHANNEL_ID=$(echo "$CHANNELS" | jq -r --arg name "$channel_name" '.[] | select(.name==$name) | .id')
162
+
163
+ if [ -z "$CHANNEL_ID" ]; then
164
+ echo "Channel #$channel_name not found" >&2
165
+ return 1
166
+ fi
167
+
168
+ echo "$CHANNEL_ID"
169
+ }
170
+
171
+ # Usage
172
+ GENERAL_ID=$(get_channel_id "General")
173
+ if [ $? -eq 0 ]; then
174
+ agent-teams message send "$GENERAL_ID" "Hello!"
175
+ fi
176
+ ```
177
+
178
+ **When to use**: When you know channel name but need the ID.
179
+
180
+ ## Pattern 5: Multi-Channel Broadcast
181
+
182
+ **Use case**: Send the same message to multiple channels
183
+
184
+ ```bash
185
+ #!/bin/bash
186
+
187
+ MESSAGE="System maintenance in 30 minutes"
188
+ CHANNEL_NAMES=("General" "Announcements" "Engineering")
189
+
190
+ # Ensure fresh token before bulk operation
191
+ agent-teams auth extract
192
+
193
+ # Get all channels once
194
+ CHANNELS=$(agent-teams channel list)
195
+
196
+ for name in "${CHANNEL_NAMES[@]}"; do
197
+ CHANNEL_ID=$(echo "$CHANNELS" | jq -r --arg n "$name" '.[] | select(.name==$n) | .id')
198
+
199
+ if [ -z "$CHANNEL_ID" ]; then
200
+ echo "Channel #$name not found, skipping"
201
+ continue
202
+ fi
203
+
204
+ echo "Posting to #$name..."
205
+ RESULT=$(agent-teams message send "$CHANNEL_ID" "$MESSAGE")
206
+
207
+ if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
208
+ echo " Posted to #$name"
209
+ else
210
+ echo " Failed to post to #$name"
211
+ fi
212
+
213
+ # Rate limit: Don't spam Teams API
214
+ sleep 1
215
+ done
216
+ ```
217
+
218
+ **When to use**: Announcements, alerts, status updates across channels.
219
+
220
+ ## Pattern 6: File Upload with Context
221
+
222
+ **Use case**: Share a file with explanation
223
+
224
+ ```bash
225
+ #!/bin/bash
226
+
227
+ CHANNEL_ID="19:abc123@thread.tacv2"
228
+ REPORT_FILE="./daily-report.pdf"
229
+
230
+ # Upload file
231
+ UPLOAD_RESULT=$(agent-teams file upload "$CHANNEL_ID" "$REPORT_FILE")
232
+
233
+ if echo "$UPLOAD_RESULT" | jq -e '.id' > /dev/null 2>&1; then
234
+ FILE_ID=$(echo "$UPLOAD_RESULT" | jq -r '.id')
235
+ echo "File uploaded: $FILE_ID"
236
+
237
+ # Send context message
238
+ agent-teams message send "$CHANNEL_ID" "Daily report is ready! Key highlights:
239
+ - 95% test coverage
240
+ - 3 bugs fixed
241
+ - 2 new features deployed"
242
+ else
243
+ echo "Upload failed: $(echo "$UPLOAD_RESULT" | jq -r '.error')"
244
+ exit 1
245
+ fi
246
+ ```
247
+
248
+ **When to use**: Automated reporting, log sharing, artifact distribution.
249
+
250
+ ## Pattern 7: User Lookup and Mention
251
+
252
+ **Use case**: Find a user and mention them in a message
253
+
254
+ ```bash
255
+ #!/bin/bash
256
+
257
+ CHANNEL_ID="19:abc123@thread.tacv2"
258
+ USERNAME="john"
259
+
260
+ # Get team members
261
+ USERS=$(agent-teams user list)
262
+ USER=$(echo "$USERS" | jq -r --arg name "$USERNAME" 'first(.[] | select(.displayName | ascii_downcase | contains($name | ascii_downcase)))')
263
+ USER_ID=$(echo "$USER" | jq -r '.id')
264
+ USER_NAME=$(echo "$USER" | jq -r '.displayName')
265
+
266
+ if [ -z "$USER_ID" ] || [ "$USER_ID" = "null" ]; then
267
+ echo "User $USERNAME not found"
268
+ exit 1
269
+ fi
270
+
271
+ # Send message with mention (Teams format)
272
+ agent-teams message send "$CHANNEL_ID" "Hey <at id=\"$USER_ID\">$USER_NAME</at>, the build is ready for review!"
273
+ ```
274
+
275
+ **When to use**: Notifications, task assignments, code review requests.
276
+
277
+ **Note**: Teams mentions use format `<at id="USER_ID">Display Name</at>`.
278
+
279
+ ## Pattern 8: Reaction-Based Workflow
280
+
281
+ **Use case**: Use reactions as simple state indicators
282
+
283
+ ```bash
284
+ #!/bin/bash
285
+
286
+ CHANNEL_ID="19:abc123@thread.tacv2"
287
+
288
+ # Send deployment message
289
+ RESULT=$(agent-teams message send "$CHANNEL_ID" "Deploying v2.1.0 to production...")
290
+ MSG_ID=$(echo "$RESULT" | jq -r '.id')
291
+
292
+ # Mark as in-progress
293
+ agent-teams reaction add "$CHANNEL_ID" "$MSG_ID" "hourglass"
294
+
295
+ # Simulate deployment
296
+ sleep 5
297
+
298
+ # Remove in-progress, add success
299
+ agent-teams reaction remove "$CHANNEL_ID" "$MSG_ID" "hourglass"
300
+ agent-teams reaction add "$CHANNEL_ID" "$MSG_ID" "checkmark"
301
+
302
+ # Send completion message
303
+ agent-teams message send "$CHANNEL_ID" "Deployed v2.1.0 to production successfully!"
304
+ ```
305
+
306
+ **When to use**: Visual status tracking, workflow states, quick acknowledgments.
307
+
308
+ ## Pattern 9: Error Handling with Token Refresh
309
+
310
+ **Use case**: Robust message sending with retries and token refresh
311
+
312
+ ```bash
313
+ #!/bin/bash
314
+
315
+ send_with_retry() {
316
+ local channel_id=$1
317
+ local message=$2
318
+ local max_attempts=3
319
+ local attempt=1
320
+
321
+ while [ $attempt -le $max_attempts ]; do
322
+ echo "Attempt $attempt/$max_attempts..."
323
+
324
+ RESULT=$(agent-teams message send "$channel_id" "$message")
325
+
326
+ if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
327
+ echo "Message sent successfully!"
328
+ return 0
329
+ fi
330
+
331
+ ERROR=$(echo "$RESULT" | jq -r '.error // "Unknown error"')
332
+ echo "Failed: $ERROR"
333
+
334
+ # Handle token expiry - refresh and retry
335
+ if echo "$ERROR" | grep -qi "expired\|401\|unauthorized"; then
336
+ echo "Token expired, refreshing..."
337
+ agent-teams auth extract
338
+ # Don't count this as an attempt
339
+ continue
340
+ fi
341
+
342
+ # Don't retry on certain errors
343
+ if echo "$ERROR" | grep -q "Channel not found"; then
344
+ echo "Channel not found - not retrying"
345
+ return 1
346
+ fi
347
+
348
+ if [ $attempt -lt $max_attempts ]; then
349
+ sleep $((attempt * 2)) # Exponential backoff
350
+ fi
351
+
352
+ attempt=$((attempt + 1))
353
+ done
354
+
355
+ echo "Failed after $max_attempts attempts"
356
+ return 1
357
+ }
358
+
359
+ # Usage
360
+ CHANNEL_ID="19:abc123@thread.tacv2"
361
+ send_with_retry "$CHANNEL_ID" "Important message!"
362
+ ```
363
+
364
+ **When to use**: Production scripts, critical notifications, unreliable networks.
365
+
366
+ ## Pattern 10: Switch Teams for Operations
367
+
368
+ **Use case**: Work with multiple Teams
369
+
370
+ ```bash
371
+ #!/bin/bash
372
+
373
+ # List all teams
374
+ TEAMS=$(agent-teams team list)
375
+ echo "Available teams:"
376
+ echo "$TEAMS" | jq -r '.[] | " \(.name) (\(.id)) \(if .current then "[current]" else "" end)"'
377
+
378
+ # Switch to a specific team
379
+ TARGET_TEAM=$(echo "$TEAMS" | jq -r '.[] | select(.name | contains("Production")) | .id')
380
+ if [ -n "$TARGET_TEAM" ]; then
381
+ agent-teams team switch "$TARGET_TEAM"
382
+ echo "Switched to Production team"
383
+ fi
384
+
385
+ # Now operations use the new team
386
+ agent-teams channel list
387
+ ```
388
+
389
+ **When to use**: Managing multiple teams, cross-team operations.
390
+
391
+ ## Pattern 11: Token Refresh Wrapper (TEAMS-SPECIFIC)
392
+
393
+ **Use case**: Wrap any operation with automatic token refresh
394
+
395
+ ```bash
396
+ #!/bin/bash
397
+
398
+ # Wrapper function that handles token refresh
399
+ teams_cmd() {
400
+ local result
401
+
402
+ # First attempt
403
+ result=$("$@" 2>&1)
404
+
405
+ # Check for token expiry
406
+ if echo "$result" | grep -qi "expired\|401\|unauthorized"; then
407
+ echo "Token expired, refreshing..." >&2
408
+ agent-teams auth extract >&2
409
+
410
+ # Retry
411
+ result=$("$@" 2>&1)
412
+ fi
413
+
414
+ echo "$result"
415
+ }
416
+
417
+ # Usage - wrap any agent-teams command
418
+ CHANNELS=$(teams_cmd agent-teams channel list)
419
+ RESULT=$(teams_cmd agent-teams message send "$CHANNEL_ID" "Hello!")
420
+ SNAPSHOT=$(teams_cmd agent-teams snapshot)
421
+ ```
422
+
423
+ **When to use**: Any script that runs for more than a few minutes.
424
+
425
+ ## Best Practices
426
+
427
+ ### 1. Always Handle Token Expiry
428
+
429
+ ```bash
430
+ # Good - handle token expiry
431
+ RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello")
432
+ if echo "$RESULT" | grep -qi "expired\|401"; then
433
+ agent-teams auth extract
434
+ RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello")
435
+ fi
436
+
437
+ # Bad - assume token is always valid
438
+ agent-teams message send "$CHANNEL_ID" "Hello"
439
+ ```
440
+
441
+ ### 2. Refresh Token Proactively for Long-Running Scripts
442
+
443
+ ```bash
444
+ # Good - check token age periodically
445
+ while true; do
446
+ STATUS=$(agent-teams auth status)
447
+ if [ "$(echo "$STATUS" | jq -r '.token_expires_soon')" = "true" ]; then
448
+ agent-teams auth extract
449
+ fi
450
+
451
+ # Do work...
452
+ sleep 60
453
+ done
454
+
455
+ # Bad - wait for failure
456
+ while true; do
457
+ agent-teams message send "$CHANNEL_ID" "Status update" # Will fail after 60-90 min
458
+ sleep 60
459
+ done
460
+ ```
461
+
462
+ ### 3. Always Get Channel IDs First
463
+
464
+ ```bash
465
+ # Good - look up channel ID
466
+ CHANNELS=$(agent-teams channel list)
467
+ CHANNEL_ID=$(echo "$CHANNELS" | jq -r '.[] | select(.name=="General") | .id')
468
+ agent-teams message send "$CHANNEL_ID" "Hello"
469
+
470
+ # Bad - hardcoded IDs without documentation
471
+ agent-teams message send "19:abc123@thread.tacv2" "Hello"
472
+ ```
473
+
474
+ ### 4. Check for Success
475
+
476
+ ```bash
477
+ # Good
478
+ RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello")
479
+ if echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
480
+ echo "Success!"
481
+ else
482
+ echo "Failed: $(echo "$RESULT" | jq -r '.error')"
483
+ fi
484
+
485
+ # Bad
486
+ agent-teams message send "$CHANNEL_ID" "Hello" # No error checking
487
+ ```
488
+
489
+ ### 5. Rate Limit Your Requests
490
+
491
+ ```bash
492
+ # Good - respect Teams API limits
493
+ for channel_id in "${CHANNEL_IDS[@]}"; do
494
+ agent-teams message send "$channel_id" "$MESSAGE"
495
+ sleep 1 # 1 second between requests
496
+ done
497
+
498
+ # Bad - rapid-fire requests
499
+ for channel_id in "${CHANNEL_IDS[@]}"; do
500
+ agent-teams message send "$channel_id" "$MESSAGE"
501
+ done
502
+ ```
503
+
504
+ ### 6. Cache Channel Lists
505
+
506
+ ```bash
507
+ # Good - fetch once, reuse
508
+ CHANNELS=$(agent-teams channel list)
509
+ for name in "${CHANNEL_NAMES[@]}"; do
510
+ id=$(echo "$CHANNELS" | jq -r --arg n "$name" '.[] | select(.name==$n) | .id')
511
+ agent-teams message send "$id" "$MESSAGE"
512
+ done
513
+
514
+ # Bad - fetch repeatedly
515
+ for name in "${CHANNEL_NAMES[@]}"; do
516
+ CHANNELS=$(agent-teams channel list) # Wasteful!
517
+ id=$(echo "$CHANNELS" | jq -r --arg n "$name" '.[] | select(.name==$n) | .id')
518
+ agent-teams message send "$id" "$MESSAGE"
519
+ done
520
+ ```
521
+
522
+ ## Anti-Patterns
523
+
524
+ ### Don't Ignore Token Expiry
525
+
526
+ ```bash
527
+ # Bad - ignores the 60-90 minute token limit
528
+ while true; do
529
+ agent-teams message list "$CHANNEL_ID" --limit 1
530
+ sleep 10
531
+ done
532
+ # Will fail silently after ~1 hour
533
+
534
+ # Good - handle token refresh
535
+ while true; do
536
+ # Check and refresh token periodically
537
+ if should_refresh_token; then
538
+ agent-teams auth extract
539
+ fi
540
+
541
+ agent-teams message list "$CHANNEL_ID" --limit 1
542
+ sleep 10
543
+ done
544
+ ```
545
+
546
+ ### Don't Poll Too Frequently
547
+
548
+ ```bash
549
+ # Bad - polls every second (may get rate limited)
550
+ while true; do
551
+ agent-teams message list "$CHANNEL_ID" --limit 1
552
+ sleep 1
553
+ done
554
+
555
+ # Good - reasonable interval
556
+ while true; do
557
+ agent-teams message list "$CHANNEL_ID" --limit 1
558
+ sleep 10 # 10 seconds
559
+ done
560
+ ```
561
+
562
+ ### Don't Ignore Errors
563
+
564
+ ```bash
565
+ # Bad
566
+ agent-teams message send "$CHANNEL_ID" "Hello"
567
+ # Continues even if it failed
568
+
569
+ # Good
570
+ RESULT=$(agent-teams message send "$CHANNEL_ID" "Hello")
571
+ if ! echo "$RESULT" | jq -e '.id' > /dev/null 2>&1; then
572
+ echo "Failed to send message"
573
+ exit 1
574
+ fi
575
+ ```
576
+
577
+ ### Don't Spam Channels
578
+
579
+ ```bash
580
+ # Bad - sends 100 messages
581
+ for i in {1..100}; do
582
+ agent-teams message send "$CHANNEL_ID" "Message $i"
583
+ done
584
+
585
+ # Good - batch into single message
586
+ MESSAGE="Updates:"
587
+ for i in {1..100}; do
588
+ MESSAGE="$MESSAGE\n$i. Item $i"
589
+ done
590
+ agent-teams message send "$CHANNEL_ID" "$MESSAGE"
591
+ ```
592
+
593
+ ## See Also
594
+
595
+ - [Authentication Guide](authentication.md) - Setting up credentials and token management
596
+ - [Templates](../templates/) - Runnable example scripts