VS Code拡張機能によるAPIキー漏洩を防ぐ方法

2026年5月20日、GitHubは、攻撃者が約3,800の内部コードリポジトリからデータを盗んだことを確認しました。侵入経路はGitHubサーバーのゼロデイではなく、従業員のノートパソコンにインストールされた不正なVS Code拡張機能でした。拡張機能は開発者と同じファイルシステム権限で動作するため、ソースコード、設定ファイル、ワークスペース内の認証情報を読み取れます。APIキーを同種の攻撃から守るには、クラウドだけでなく、開発者マシンとそこで動くツールを前提に対策する必要があります。

今すぐApidogを試す

TL;DR(要するに)

侵害されたIDE拡張機能や流出したリポジトリからAPIキーを守るには、開発ツールが読める場所にアクティブな認証情報を置かないことが重要です。

実施すべきことは次の通りです。

  • シークレットをソースコードにハードコードしない
  • 実キー入りの .env をコミットしない
  • .gitignore をセキュリティ制御として扱わない
  • キーを環境ごとに分離する
  • 最小権限・短命の認証情報を使う
  • 定期的にローテーションする
  • APIクライアントでは、プレーンテキストファイルではなく環境変数やローカル値を使う

Apidogのようなツールを使うと、API認証情報をリポジトリやワークスペース内のプレーンテキストではなく、環境変数やローカル専用値として扱いやすくなります。

なぜGitHubの侵害はすべての開発者にとって警鐘なのか

GitHubのインシデントは、典型的なサプライチェーン攻撃です。TeamPCPとして追跡されている脅威グループは、npm、PyPI、PHPエコシステムでトロイの木馬化されたパッケージを使ってきた経緯があります。今回は、悪意のあるペイロードがVS Code拡張機能経由で侵入しました。

TechCrunchの報道によると、攻撃者は約3,800の内部リポジトリからデータを持ち出し、アンダーグラウンドフォーラムで5万ドル以上で販売しているとされています。GitHubは、これらの内部リポジトリ外に保存された顧客データが影響を受けた証拠はないと述べており、調査は継続中です。

ここで重要なのは、VS Code拡張機能が「単なるコード」だという点です。インストールすると、ユーザー権限でエディタプロセス内で実行されます。つまり、次のようなことが可能です。

  • ディレクトリを一覧表示する
  • ファイルを開いて読む
  • ファイル変更を監視する
  • 外部ネットワークへリクエストする

これは脆弱性ではなく、拡張機能モデルの通常動作です。多くの拡張機能は正当にファイルアクセスを必要とします。問題は、悪意のある、または侵害された拡張機能も同じ権限を使えることです。

典型的なプロジェクトでは、攻撃者が次のようなファイルを探します。

  • リポジトリルートの .env
  • config/secrets.yml
  • テスト用スクリプトに残ったハードコード済みトークン
  • ~/.aws/credentials
  • 認証トークン入りの .npmrc
  • SSHキー
  • CI/CDやクラウド、AIツール関連の認証情報

TeamPCPは、「Mini Shai-Hulud」npmワームキャンペーンの背後にいる攻撃者でもあり、感染したマシンから開発者、CI/CD、クラウド、AIツール関連の認証情報を収集しました。パターンは同じです。開発者マシンでコードを実行させ、認証情報らしきものを探します。

同様の露出パターンは、Vercel侵害から得られたAPIセキュリティの教訓や、npmサプライチェーンセキュリティガイドでも扱われています。

今確認すべき問いはシンプルです。

もし今、自分のエディタで悪意のある拡張機能が実行されたら、何が持ち出されるか?

ハードコードされたキーとコミットされた .env は常に負債になる

多くの認証情報漏洩は高度な攻撃ではありません。原因は単純です。

  • 開発者が「一時的に」コードへキーを貼り付けた
  • .env ファイルを誤ってコミットした
  • テストスクリプトに本番トークンを残した
  • Git履歴から削除したつもりでローテーションしていない

たとえば、次のようなコードです。

import requests

# paymentsエンドポイントのクイックテスト
STRIPE_KEY = "sk_live_51Qk2mNExampleKeyDoNotShipThis"

response = requests.post(
    "https://api.stripe.com/v1/charges",
    auth=(STRIPE_KEY, ""),
    data={"amount": 2000, "currency": "usd", "source": "tok_visa"},
)

print(response.json())

この sk_live_ キーは、すでにファイルの一部です。ワークスペース内にあるため、任意の拡張機能が読み取れます。さらにコミットされると、後で行を削除してもGit履歴に残ります。

.env はハードコードよりは良い方法です。たとえば次のように、実行時に読み込む形にできます。

# .env (実行時にロードされ、出荷されることを意図しない)
DATABASE_URL=postgres://app_user:Zk7%[email protected]:5432/payments
STRIPE_SECRET_KEY=sk_live_51Qk2mNExampleKeyDoNotShipThis
OPENAI_API_KEY=sk-proj-aB3dEf9hKlMnOpQrStUvWxYz1234567890
AWS_ACCESS_KEY_ID=AKIA4EXAMPLE7QRSTUVW
AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
JWT_SIGNING_SECRET=8f2a91c4e7b6d3508f2a91c4e7b6d350

ただし、.env は万能ではありません。ファイルは依然としてワークスペース内にプレーンテキストで存在します。悪意のある拡張機能にとって、シークレットが app.py にあるか .env にあるかは重要ではありません。どちらもファイルであり、読み取れます。

.env が解決するのは、「シークレットをソースコードから分離する」問題です。しかし、次の問題は解決しません。

  • .env がコミットされる問題
  • ローカルツールが .env を読む問題
  • Git履歴に残ったシークレットの問題
  • 本番キーが開発者マシンに存在する問題

コミットされた .env は特に危険です。開発者が .env.example をコピーして .env を作り、本番キーを入れたあと、git add . で一緒に追加してしまうケースは珍しくありません。リポジトリが公開、ミラー、侵害された時点で、そのキーは漏洩したものとして扱うべきです。

リポジトリ漏洩の観点は、APIドキュメントとGitリポジトリのセキュリティでも詳しく解説されています。

.gitignore はセキュリティ制御ではない

.gitignore に .env を追加すると、守られているように感じます。しかし実際には、.gitignore は「このファイルを拾わないでください」というGit向けの指示にすぎません。

.gitignore が行うことは限定的です。git add 実行時に、パターンに一致する未追跡ファイルをスキップします。それだけです。

重要な失敗モードは3つあります。

1. すでに追跡されているファイルには効かない

.env を一度でもコミットしていた場合、後から .gitignore に追加してもGitは追跡を続けます。

git rm --cached .env
git commit -m "Remove .env from tracking"

この操作で現在の追跡は止められますが、過去のコミットにはシークレットが残ります。

2. ディスク上のファイルには効かない

.gitignore はGitの挙動を変えるだけです。.env ファイル自体はワークスペースに残ります。悪意のあるVS Code拡張機能はGitインデックスではなくファイルシステムを読み取ります。

つまり、.gitignore はローカルツールに対する防御にはなりません。

3. 簡単にバイパスできる

次のような操作で無視ルールは回避できます。

git add -f .env

エディタのソース管理UIやサブディレクトリの設定によって、意図せず追加される可能性もあります。

過去に .env がコミットされたか確認するには、次のコマンドを使います。

# 現在「無視されている」場合でも、そのファイルを触ったすべてのコミットをリスト表示
git log --all --full-history --oneline -- .env

# 履歴に残っている実際のシークレット値を確認
git log -p --all -- .env | grep -iE "key|secret|token|password"

何か見つかった場合、その認証情報は漏洩済みとして扱ってください。対応は次の順序です。

  1. キーをローテーションする
  2. 影響範囲を確認する
  3. git filter-repo などで履歴から削除する
  4. チームとリモート履歴の更新を調整する
  5. 再発防止として、アクティブな認証情報をファイルから移動する

.gitignore は便利です。正直なミスを減らし、差分をきれいに保てます。しかし、防御境界として扱ってはいけません。

被害範囲を縮小する4つの習慣

認証情報が絶対に漏洩しないことは保証できません。しかし、漏洩したキーの価値を小さくすることはできます。

実装すべき習慣は次の4つです。

  1. スコープする
  2. 分離する
  3. 短命にする
  4. ローテーションする

1. シークレットを環境にスコープする

同じAPIキーを開発、ステージング、本番で使い回さないでください。1つのキーが漏洩すると、すべての環境が同時に危険になります。

環境ごとに別の認証情報を使います。

環境 使うべきキー アクセス範囲
ローカル開発 開発キー サンドボックス、テストデータ
ステージング ステージングキー ステージング環境のみ
本番 本番キー 本番ランタイムのみ

開発キーが漏洩しても、攻撃者が到達できるのはテストデータだけにするのが目標です。

2. 環境を分離する

環境分離とは、単にキーの値を分けることではありません。環境同士が到達できない構成にすることです。

たとえば、次のようにします。

  • 開発DBは本番DBのリードレプリカにしない
  • ステージングの決済プロバイダーはテストモードを使う
  • 開発用設定から本番データに接続できないようにする
  • 本番キーをローカルマシンにコピーしない

「このキーはどの環境のものか?」に明確に答えられる状態を作ってください。その答えが、漏洩時の深刻度を決めます。

3. 最小権限・短命のキーを使う

盗まれたキーの危険度は、主に2つで決まります。

権限

キーには、そのタスクに必要な最小権限だけを与えます。

たとえば、公開製品カタログを読み取るだけのフロントエンドビルドに必要なのは、読み取り専用キーです。書き込み権限、請求権限、管理者権限は不要です。

多くのAPIプロバイダーは、スコープ付きキーや細粒度トークンをサポートしています。GitHubの細粒度パーソナルアクセストークンは良い例です。

トークン方式を検討する場合は、APIキーとOAuthの比較記事も参考になります。短命なOAuthトークンが静的キーより適しているケースがあります。

寿命

1時間で期限切れになるキーは、攻撃者にとって価値が低くなります。盗まれたデータセットが売買され、攻撃者がキーを試す頃には無効になっている可能性が高いからです。

一方、無期限の静的キーは危険です。誰かが気づくまで機能し続けます。

実装方針は次の通りです。

  • 可能ならオンデマンド発行の短命トークンを使う
  • 静的キーが必要な場合でも有効期限を設定する
  • 高権限キーほど寿命を短くする
  • 本番キーを長期間放置しない

4. パニック時ではなく、スケジュールでローテーションする

ローテーションとは、古い認証情報が使えなくなるようにキーの値を変更することです。

多くのチームは、漏洩後に慌ててローテーションします。しかし、そのタイミングで手順が未整備だと、復旧が遅れます。

事前にスケジュール化してください。

例:

認証情報 ローテーション頻度
高権限の本番キー 毎月
通常の本番キー 1〜3か月ごと
ステージングキー 四半期ごと
開発キー 四半期ごと、または退職・端末紛失時

定期ローテーションには2つの効果があります。

  1. 未検出の漏洩があっても有効期間を短くできる
  2. ローテーション手順が日常作業になり、インシデント時に慌てない

関連ツールについては、APIキー管理ツールのまとめも参考になります。

認証情報をワークスペースに散乱させず、Apidogの環境変数に保持する

正直に言うと、ApidogもVS Code拡張機能とMCPサーバーを提供しています。ここで主張したいのは、「特定のクライアントツールはサプライチェーン攻撃に免疫がある」ということではありません。クライアント側ツールに絶対の免疫はありません。

重要なのは、シークレットがどこに存在するかです。

API開発では、次のような値を頻繁に扱います。

  • Bearerトークン
  • APIキー
  • データベース接続文字列
  • JWT署名用シークレット
  • サードパーティAPIの認証情報

デフォルトの行動は、これらを .env やテストスクリプトに置くことです。しかし、それではアクティブな認証情報がワークスペース内のプレーンテキストファイルに残ります。これは、悪意のある拡張機能が探す対象そのものです。

Apidogの環境システムを使うと、これらの値をリクエスト定義から分離できます。

プレーンテキストファイルではなく環境変数を使う

Apidogでは、認証情報をリポジトリ内のテキストではなく、環境変数として保存できます。

リクエストでは、実値ではなく変数名を参照します。

Authorization: Bearer {{access_token}}

避けるべき例は次のような形です。

Authorization: Bearer sk-proj-aB3dEf9hKlMnOpQrStUvWxYz1234567890

変数を使えば、リクエスト定義に実際のシークレットを書かずに済みます。送信時にApidogが値を解決します。

この構成により、認証情報はソースコードや .env の隣にあるプレーンテキスト行ではなく、APIクライアント内の管理された値として扱われます。

ローカル値でシークレットをマシンに留める

Apidogでは、変数に対して共有値とローカル値を分けられます。

  • 共有値または初期値: チームに共有される値
  • ローカル値または現在値: 自分のマシンに残る値

トークンやパスワードなどの機密データは、ローカル値に入れるべきです。これにより、プロジェクト構造を共有しても、実際のシークレットは同期されません。

チームメイトが取得するのは、たとえば次のような変数名と構造です。

access_token
db_password
payment_api_key

しかし、あなたの実際の値は共有されません。各開発者が自分のローカル値を入力します。

この設計により、次のリスクを減らせます。

  • 実キー入りの .env を共有する
  • 本番トークンをAPIリクエスト定義に保存する
  • チーム全員に同じ認証情報を配る
  • リポジトリや同期データに実シークレットが混入する

環境管理で開発・ステージング・本番を分ける

Apidogの環境管理では、開発、ステージング、本番などの環境を定義できます。それぞれに異なるベースURLと変数値を設定できます。

例:

変数 開発 ステージング 本番
base_url https://dev-api.example.com https://stg-api.example.com https://api.example.com
payment_api_key サンドボックスキー テストモードキー 本番キー
access_token 開発用トークン ステージング用トークン 本番用トークン

リクエスト側は同じままです。

GET {{base_url}}/orders
Authorization: Bearer {{access_token}}

環境を切り替えると、参照される値のセットが切り替わります。リクエストを編集して本番キーを貼り直す必要はありません。

これにより、次のような運用がしやすくなります。

  • 開発環境ではサンドボックスキーだけを使う
  • 本番キーをローカル開発に持ち込まない
  • 環境ごとの認証情報を明確に分離する
  • 誤って開発キーで本番APIを叩くリスクを減らす

厳密な境界線が必要なチーム向け: Vaultシークレット

本番シークレットをAPIクライアントに直接保存したくないチームでは、Apidog EnterpriseプランのVaultシークレット機能を利用できます。

Vaultシークレットは、次のような専用シークレットマネージャーから値を取得します。

  • HashiCorp Vault
  • Azure Key Vault
  • AWS Secrets Manager

ApidogはVaultのパスやメタデータのみを保存します。実際のシークレット値はオンデマンドで取得され、プロジェクト経由でチームメイトに共有されません。

本番認証情報の保管場所を、専用のシークレットマネージャーに維持できるのがポイントです。

Apidogで実装する手順

API認証情報を .env からApidogの環境変数へ移すには、次の流れで進めます。

  1. Apidogをダウンロードする
  2. プロジェクトを作成する
  3. 環境管理を開く
  4. development、staging、production などの環境を作成する
  5. access_token や payment_api_key などの変数を追加する
  6. 機密値はローカル値として入力する
  7. リクエストでは {{access_token}} のように参照する
  8. .env やスクリプトから実キーを削除する
  9. 過去にコミット済みならキーをローテーションする

注意点として、シークレットをApidogに移すことで、リポジトリやワークスペース内のプレーンテキスト認証情報は減らせます。しかし、マシン自体が侵害されたツールに対して無敵になるわけではありません。

引き続き、次の対策は必要です。

  • インストールする拡張機能を監査する
  • 不要な拡張機能を削除する
  • 本番キーを最小権限にする
  • 短命な認証情報を使う
  • スケジュールに従ってローテーションする

Apidogは「認証情報をどこに置くか」の問題を改善します。端末全体の防御は、引き続き多層防御で考える必要があります。

結論

GitHubの侵害が示したのは、攻撃者が開発者マシンを狙っているという現実です。信頼されたエディタ、便利な拡張機能、プレーンテキストの設定ファイルがそろった環境は、本番サーバーよりも柔らかい標的になり得ます。

今すぐできる監査は次の通りです。

# よくあるシークレット名を検索
grep -RniE "key|secret|token|password" .

# .env が履歴にあるか確認
git log --all --full-history --oneline -- .env

# 履歴内のシークレットらしき値を確認
git log -p --all -- .env | grep -iE "key|secret|token|password"

何か見つかった場合は、漏洩済みとして扱います。

  1. 該当キーをローテーションする
  2. 影響範囲を確認する
  3. Git履歴から削除する
  4. アクティブな値をプレーンテキストファイルから移す
  5. 今後は環境変数、ローカル値、Vault連携を使う

次のAPI認証情報から、.env やスクリプトに実キーを置くのをやめてください。Apidogをダウンロードし、環境変数として管理するだけでも、ワークスペース内に露出するシークレットを減らせます。

より広い文脈については、GitHub侵害後のセルフホスト型APIツールとAPIキー管理ツールも参考になります。

よくある質問

VS Code拡張機能は本当に .env ファイルやAPIキーを読み取れますか?

はい。VS Code拡張機能は、ユーザーアカウントのファイル権限でエディタプロセス内で実行されます。ディレクトリの一覧表示、ファイルのオープン、.env、設定ファイル、~/.aws/credentials などの読み取りが可能です。

これは多くの場合、通常の拡張機能動作です。問題は、悪意のある、または侵害された拡張機能が同じアクセス権を使ってシークレットを収集できることです。

.gitignore に .env を追加するだけでAPIキーを保護できますか?

いいえ。.gitignore は、未追跡ファイルを git add から除外するだけです。

次のものは保護できません。

  • すでにGitで追跡されている .env
  • Git履歴に残ったシークレット
  • ディスク上に存在する .env
  • ローカルツールや拡張機能による読み取り

.gitignore はミスを減らすための衛生対策であり、セキュリティ境界ではありません。

Git履歴にAPIキーを見つけた場合、どうすべきですか?

リポジトリがプライベートでも、直ちに侵害済みとして扱ってください。

対応手順は次の通りです。

  1. キーをローテーションする
  2. 該当キーの利用ログを確認する
  3. git filter-repo などで履歴から削除する
  4. チームと調整してクリーンな履歴を反映する
  5. アクティブな認証情報をプレーンテキストファイルから移す

継続的な運用については、APIキー管理ツールも参考になります。

ApidogにAPIキーを保存すると、露出はどのように減りますか?

Apidogでは、認証情報を環境変数として保存し、リクエスト内では名前で参照できます。

Authorization: Bearer {{access_token}}

これにより、実際のシークレットをリポジトリ内の .env やスクリプトに直接置く必要が減ります。また、ローカル専用値を使えば、トークンやパスワードをサーバーやチームメイトに同期せず、自分のマシンに留められます。

ただし、これは端末が侵害された場合の完全な防御ではありません。拡張機能の監査、最小権限、短命キー、ローテーションは引き続き必要です。

ApidogもVS Code拡張機能を持っていますが、それはリスクですか?

はい、ApidogはVS Code拡張機能とMCPサーバーを提供しています。この記事の要点は、特定のクライアントツールがサプライチェーン攻撃に免疫を持つということではありません。

重要なのは、シークレットがどこに存在するかです。認証情報をローカル専用値やVault連携に置くことで、ワークスペース内のプレーンテキストキーを減らせます。これは、マシン上のどのツールが侵害された場合でも、スクレイピング対象を減らすための対策です。

APIキーのスコープ設定とローテーションの違いは何ですか?

スコープ設定は、キーができることを制限します。

例:

  • 開発キーはサンドボックスのみ
  • 読み取り専用キーは書き込み不可
  • 決済キーは決済APIだけに限定

ローテーションは、古いキーを無効化し、新しい値へ切り替えることです。

スコープ設定は漏洩時の被害を小さくします。ローテーションは漏洩キーが使える期間を短くします。両方が必要です。

APIキーはどのくらいの頻度でローテーションすべきですか?

インシデント後だけでなく、固定スケジュールでローテーションしてください。

目安は次の通りです。

  • 高権限の本番キー: 毎月
  • 通常の本番キー: 1〜3か月ごと
  • ステージングキー: 四半期ごと
  • 開発キー: 四半期ごと、または端末紛失・退職時

チームのリスク許容度やコンプライアンス要件に合わせて調整してください。

本番APIキーは開発者のノートパソコンに置くべきですか?

理想的には、置くべきではありません。本番認証情報は、可能な限り少ない場所に存在すべきです。通常は、専用のシークレットマネージャーと本番ランタイムに限定します。

開発者は、非本番データにスコープされた開発用またはステージング用の認証情報で作業すべきです。ノートパソコンが侵害されても、攻撃者が到達できるのはサンドボックスに限定される状態を目指してください。

Temporal Cloud Serverless: Durable Execution Without the Ops Overhead

If you’ve evaluated Temporal before and decided the ops surface was too heavy, the picture has shifted. At Replay 2026, Temporal announced Serverless Workers — currently in pre-release — which run your Temporal Workers on AWS Lambda rather than a persistent fleet you manage. The core programming model stays the same, but Temporal now handles invoking, scaling, and shutting down the Lambda functions based on queue depth. You write the same Workflows and Activities you’d write for a self-hosted cluster; what disappears is the always-on compute bill and the autoscaling strategy.

Before getting into the specifics of what changed, it’s worth being clear about what Temporal actually is and why the serverless announcement matters in context.

What Durable Execution Actually Means

Temporal’s core abstraction is that your code runs to completion regardless of failures — process crashes, network partitions, infrastructure restarts. It achieves this by recording every step of a Workflow’s execution as an event history on the Temporal Service. If a Worker crashes mid-execution, another Worker picks up the history, replays it to reconstruct in-memory state, and continues from where things stopped.

The practical result: you write business logic as ordinary functions without embedding retry loops, checkpoint files, or manual state management. A Workflow that transfers funds, processes a batch of documents, or runs a multi-step ML pipeline looks like sequential code. The durability comes from Temporal’s event log, not from your code’s defensive patterns.

The unit of work is split into two layers. Workflows define the control flow — what happens, in what order, with what branching logic. Activities are the side-effectful units that talk to databases, APIs, or external services. Activities get automatic retry policies; Workflows don’t execute side effects directly, which is what makes replay safe.

Workers are the processes that actually execute this code. They poll a Task Queue on the Temporal Service, pull tasks, run them, and report results back. Traditional Temporal deployments require you to run long-lived Worker processes — on Kubernetes, EC2, ECS, wherever — and manage their scaling yourself.

Temporal’s event replay model means that Workflow code must be deterministic: the same inputs must always produce the same sequence of commands. Non-deterministic operations (network calls, random numbers, wall-clock time) belong in Activities, not in the Workflow function itself. This constraint is enforced by the SDK rather than the runtime, so violating it produces subtle bugs rather than immediate errors. Every major Temporal SDK ships a linter or analyzer to catch common violations before they reach production.

Serverless Workers: What Changed at Replay 2026

Serverless Workers are a different lifecycle model for the same programming model. Instead of a long-running process polling the queue continuously, you upload your Worker code to AWS Lambda, create a cross-account IAM role using a Temporal-provided CloudFormation template, and register the Lambda ARN with Temporal via CLI or UI.

From there, Temporal watches the Task Queue metrics — specifically the backlog count and sync match rate — and decides when to invoke your Lambda. When tasks arrive, Temporal assumes the IAM role in your account and triggers the function. The Worker processes available tasks and shuts down before Lambda’s maximum invocation duration.

The setup is intentionally minimal: three steps, standard SDK code, no new APIs to learn. The pre-release currently supports Go, Python, and TypeScript SDKs. Google Cloud Run support is listed as coming.

The scaling model changes meaningfully. With a traditional Worker fleet, you define autoscaling policies and pay for minimum capacity even during quiet periods. With Serverless Workers, compute runs only when tasks exist. For workloads that are bursty, infrequent, or unpredictable in volume — background jobs, triggered pipelines, intermittent integrations — this eliminates a real cost and operational surface.

The Constraint You Can’t Ignore

Lambda imposes a maximum invocation duration of 15 minutes. Temporal handles this cleanly at the Workflow level — a Workflow can span arbitrarily many Lambda invocations across its lifetime, because the state lives in the event log, not in the process. But individual Activities are bounded by that 15-minute ceiling.

If you have an Activity that calls a slow external API, runs a database migration, or performs a computation that regularly takes longer than 15 minutes, Serverless Workers are the wrong fit for those activities. Long-running Workflows are supported; long-running Activities within a single invocation are not. This is a real limitation for ML training steps, video encoding, or any processing that cannot be broken into chunks under the time limit.

The Temporal team is candid about this tradeoff in the documentation. It’s not a workaround-able edge case — it’s an architectural constraint of the underlying compute platform.

Why This Matters for AI Agent Workflows

The timing of the serverless announcement is not accidental. AI agent architectures have become one of Temporal’s fastest-growing use cases, and the two are naturally complementary for reasons that go beyond marketing alignment.

Agentic workflows are structurally difficult: they run for unpredictable durations, call unreliable APIs (LLM providers, external tools, retrieval systems), branch based on model outputs, and need to be observable and recoverable when something goes wrong. Temporal’s primitives address each of these directly.

Also announced at Replay 2026 alongside Serverless Workers:

  • Workflow Streams (public preview): A durable streaming primitive using Signals and Updates that delivers incremental outputs — useful for streaming token-by-token LLM responses through a durable layer rather than buffering everything in memory.
  • External Payload Storage (public preview for Python and Go): Routes large inputs and outputs through Amazon S3 or custom storage drivers, sidestepping Temporal’s payload size limits when you’re passing large context windows or embedding vectors between steps.
  • Google ADK and OpenAI Agents SDK integrations: Official integrations that give agent frameworks access to Temporal’s durability primitives without manual wiring.

For multi-agent systems specifically, Temporal’s Signals and Queries give you a structured inter-agent messaging layer backed by the event log. Each agent is a separate Workflow; Signals pass messages between them; Queries expose current state without mutating it. The Temporal UI records every inter-agent communication with timestamps and inputs, which converts the usual opacity of agent orchestration into something you can actually inspect and debug.

The Serverless Workers model fits agent workloads that are event-triggered — a new document arrives, a user submits a form, a schedule fires. Those agents don’t need always-on Workers. They need Workers that start in response to demand and stop when the queue is empty.

Pre-release software carries real caveats. Serverless Workers are not yet at general availability, which means APIs, CloudFormation templates, and CLI commands may change before the stable release. If you plan to build production systems on this today, pin your Temporal SDK versions and follow the release notes closely. The Temporal team has a history of maintaining backward compatibility across SDK versions, but pre-release features are explicitly outside that guarantee.

Pricing and When the Model Makes Sense

Temporal Cloud bills on actions — billable operations between your application and the Temporal Service, such as starting a Workflow, recording a heartbeat, or sending a Signal. Published pricing starts at $50 per million Actions with volume discounts applied automatically as usage grows. Storage is billed separately: active storage (running Workflows) and retained storage (event histories for closed Workflows, up to a 90-day retention window).

The base plan tiers start at $100/month for Essentials and $500/month for Business. These include baseline action and storage allocations before consumption billing kicks in.

Serverless Workers don’t introduce a new Temporal billing line — you still pay for Actions and Storage as usual. What changes is your compute bill: Lambda invocations instead of persistent EC2 or Kubernetes nodes. For workloads running continuously at high volume, the Lambda cost per invocation can exceed what you’d pay for a small always-on fleet. The break-even depends on your specific invocation pattern and Lambda configuration, and Temporal’s own documentation on estimating costs is worth reading before committing.

The model makes the clearest sense for:

  • Background job pipelines where tasks arrive in unpredictable bursts
  • Development and staging environments where you want Temporal’s durability semantics without paying for idle Workers
  • Early-stage products where you’re not yet sure whether the workload justifies dedicated infrastructure
  • Agent systems where each workflow execution is triggered by an external event rather than running continuously

It makes less sense for latency-sensitive workflows (Lambda cold starts add tail latency you can’t fully control), high-throughput steady-state processing (at sufficient volume, long-lived Workers are cheaper), or any use case involving Activities that approach or exceed the 15-minute Lambda limit.

The Broader Picture

Temporal has grown from a Cadence fork to a funded company with over 3,000 paying customers, a managed cloud product, and now a serverless deployment mode. The programming model has stayed stable enough that early-adopter code from three years ago largely still works. That’s genuinely unusual for infrastructure tooling.

What’s changed is the deployment surface. Self-hosted Temporal clusters require Kubernetes and a production-grade persistence store (PostgreSQL or Cassandra). Temporal Cloud removes the cluster ops but still assumed you ran your own Workers. Serverless Workers remove the Worker ops. The progression is coherent.

The remaining question for most teams is whether the Temporal programming model — deterministic Workflows, separate Activities, replay-based recovery — is the right abstraction for their workload. If it is, the serverless option removes the last significant deployment objection. If it isn’t, serverless Workers don’t change the fundamental model fit. That evaluation still requires reading the documentation, running the hello-world, and stress-testing the determinism constraints against your actual code.

The pre-release is open. The setup is documented. Whether the 15-minute Activity limit and Lambda cold-start tail latency are acceptable depends on your workload, and that’s something only you can benchmark.

Originally published at pickuma.com. Subscribe to the RSS or follow @pickuma.bsky.social for new reviews.

Why Freshers Must Build Real AI Products Instead of Endless App Clones

Stop Complaining. Start Building.

Why Freshers Must Build Real AI Products Instead of Endless App Clones

Every day, freshers complain:

  • “There are no jobs.”
  • “Companies only want experienced developers.”
  • “The market is saturated.”
  • “React Native has too much competition.”
  • “AI will replace developers.”

But here is the uncomfortable truth:

Most freshers are not building real products.

They are cloning:

  • WhatsApp
  • Instagram
  • Netflix
  • Spotify
  • YouTube

Again and again.

A clone project is fine for learning basics.
But cloning alone will never make you stand out.

A recruiter has already seen:

  • 10,000 To-Do apps
  • 5,000 Chat app clones
  • 20,000 Weather apps
  • Infinite “Expense Tracker” projects

What they have not seen is:

  • A real AI accessibility app
  • An offline on-device assistant
  • A healthcare AI tool
  • A practical problem-solving app
  • A unique product solving a real human pain point

That is the difference.

The People Winning Are Not Waiting for Permission

Look at opportunities like the Gemma 4 Challenge by DEV + Google.

Five winners.
$500 each.

For many freshers in India, ₹45,000 is nearly:

  • 1–2 months of salary
  • or even more than their first internship stipend

But the money is not even the biggest reward.

The real rewards are:

  • Recognition
  • Portfolio strength
  • Confidence
  • Networking
  • Learning
  • Public credibility
  • Real-world building experience

And even if you do not win?

You still learn something priceless:
where you are weak.

That feedback is more valuable than another cloned food delivery app.

Complaining vs Building

Complaining gives emotional relief.

Building gives transformation.

There is a massive difference.

A person who spends:

  • 6 months complaining on LinkedIn
    vs
  • 6 months building real AI products

…will not end up in the same place.

The market rewards builders.

Not complainers.

The Ramayana Lesson Most People Ignore

In the Ramayana, there was a powerful warrior called Bali.

There are many interpretations of his story, but one perspective always inspired me:

Bali was not just strong.
He had the ability to quickly understand and adapt during battle.

He learned while fighting.

That combination made him dangerous:

  • strength
  • observation
  • adaptation
  • technique

Many freshers today already have talent.

The problem is not talent.

The problem is:
they never learn the technique.

They watch achievers but do not study them.

They scroll success stories but never analyze:

  • How was the product built?
  • Why did it succeed?
  • What problem does it solve?
  • What technology stack was used?
  • Why is it different?

If you learn techniques from achievers, your growth becomes much faster.

Why AI Challenges Matter So Much in 2026

We are entering a new phase of software development.

Earlier:

  • knowing React Native was enough
  • knowing backend was enough
  • knowing DSA was enough

Now?

AI integration is becoming a core engineering skill.

The developers who survive the next 5–10 years are the ones who can:

  • integrate AI
  • optimize AI
  • build practical AI tools
  • create AI-powered user experiences
  • run models locally
  • solve real-world problems

That is why challenges like the Gemma 4 Challenge matter.

They force you to:

  • think differently
  • solve actual problems
  • build complete products
  • work with modern AI models
  • learn rapidly

What is Gemma 4?

Gemma is Google’s family of lightweight open AI models designed for developers.

The goal is simple:

Give developers powerful AI capabilities that can run:

  • locally
  • efficiently
  • on consumer hardware
  • even on mobile devices in some cases

Unlike giant cloud-only models requiring expensive infrastructure, Gemma models are designed to be more accessible to developers and startups.

That is important for freshers because:
you can actually experiment without building a million-dollar infrastructure.

Why Gemma 4 Is Exciting for Mobile Developers

For mobile developers, especially React Native and Android developers, this changes everything.

Imagine building apps that can:

  • understand speech
  • summarize conversations
  • help visually impaired users
  • detect objects
  • assist students
  • provide mental wellness support
  • translate offline
  • tutor users
  • analyze documents

…without always depending on cloud APIs.

This is huge.

Because:

  • offline AI improves privacy
  • latency becomes lower
  • costs become manageable
  • apps become smarter
  • users trust local processing more

Understanding Gemma 4 Models

Gemma 4 comes in different sizes.

Generally, smaller models:

  • are faster
  • consume less RAM
  • are easier for edge devices

Larger models:

  • are smarter
  • better at reasoning
  • require stronger hardware

Some models are optimized for:

  • lightweight deployment
  • local inference
  • edge AI
  • efficient performance

This matters because your app architecture depends heavily on model size.

For example:

Smaller Edge Models

Good for:

  • mobile AI assistants
  • accessibility apps
  • offline tools
  • smart UI interactions

Larger Models

Good for:

  • complex reasoning
  • research tools
  • advanced tutoring
  • multi-step workflows

“But I Am Just a Fresher…”

That is exactly why you should start now.

The industry resets during technology shifts.

AI is one of those resets.

A fresher building practical AI apps today can sometimes stand out more than:

  • experienced developers stuck in old patterns
  • developers who never adapted
  • engineers afraid of AI

This is your opportunity window.

Do not waste it.

5 Real AI Product Ideas You Can Build with Gemma 4

1. Hearing Buddy App

An app for people who can speak but cannot hear properly.

How it works:

  • The app listens to surrounding speech
  • Converts speech to text in real time
  • Displays it on screen
  • User reads and responds normally

Why this matters:

  • Accessibility
  • Real-world impact
  • Emotional value
  • Social usefulness

This is not a clone app.

This solves a real problem.

2. Assistive Vision for Visually Impaired Users

Using camera + on-device AI.

Features:

  • Detect doors
  • Detect stairs
  • Detect obstacles
  • Detect people
  • Voice guidance

Possible stack:

  • React Native
  • VisionCamera
  • ExecuTorch
  • Gemma-based reasoning layer

This is the kind of project recruiters remember.

3. AI Study Companion

Not another chatbot.

A real education assistant that:

  • explains concepts simply
  • creates quizzes
  • tracks weak areas
  • motivates students
  • summarizes notes
  • works offline for low-connectivity regions

Huge potential in India.

4. Mental Wellness Companion

A lightweight emotional support app.

Features:

  • journaling
  • emotional check-ins
  • reflective conversations
  • mood summaries
  • breathing guidance

The focus should not be pretending to replace therapists.

The focus should be:
helping people feel heard.

5. Offline AI Travel Assistant

Useful in low-network environments.

Capabilities:

  • local translation
  • local recommendations
  • emergency guidance
  • itinerary summaries
  • tourist help

Especially useful in remote areas.

What Recruiters Actually Want

Many freshers think recruiters only care about:

  • DSA
  • LeetCode
  • CGPA

Those matter.

But real product thinking matters too.

When recruiters see:

  • originality
  • architecture understanding
  • problem solving
  • deployment knowledge
  • AI integration
  • performance optimization
  • real-world usability

…you instantly become different.

Because now you are no longer “just another fresher.”

You are a builder.

Follow Achievers Differently

Do not follow achievers for motivation only.

Study them.

Analyze:

  • how they think
  • how they learn
  • how they ship products
  • how they present work
  • how they explain ideas
  • how they solve problems

Learning the technique changes everything.

Your First Product Does Not Need to Be Perfect

Your first AI app:

  • may fail
  • may be buggy
  • may not scale
  • may not win competitions

That is normal.

The goal is not perfection.

The goal is transformation.

Every real product teaches:

  • architecture
  • debugging
  • UX
  • optimization
  • deployment
  • communication
  • resilience

Cloning teaches only imitation.

Final Thought

The future belongs to builders.

Not complainers.

If you truly want:

  • jobs
  • recognition
  • growth
  • income
  • opportunities

…then start building products that solve real human problems.

Participate in challenges.
Experiment with AI.
Fail.
Learn.
Improve.
Repeat.

You already have talent.

Now learn the technique.

And once talent meets technique, everything changes.

Join the WhatsApp Community 🚀

If you want more updates like this:

  • AI app ideas
  • React Native learning
  • On-device AI concepts
  • Challenge opportunities
  • Product-building guidance
  • Career growth discussions

Then join the WhatsApp community TechCraft By Subrata and become part of the journey.

Especially join if you are:

  • an aspiring React Native developer
  • a fresher trying to stand out
  • interested in AI + mobile apps
  • someone who wants to build real products instead of clones
  • an early supporter of practical AI learning

Your next opportunity may start from one project you decide to build today.

I Built a Dynamic llms.txt for Next.js. Then Google Said Don’t Bother.

Two weeks ago I shipped a dynamic llms.txt and llms-full.txt for a Next.js 16 site I run. Hourly revalidation, pulls from the same content sources as the sitemap, auto-categorizes by URL pattern, returns proper text/plain. Took about 40 minutes to build.

Last week Google published their AI Search optimization guide.

The relevant line:

Don’t create llms.txt files and other “special” markup.

So now I have a dynamic llms.txt that the search engine I most care about explicitly says not to bother with.

I’m keeping it anyway. Here’s why, and here’s the code in case you want to do the same.

What llms.txt is supposed to do

The llms.txt spec was proposed in 2024 (by Jeremy Howard at Answer.AI) as a way for sites to give AI assistants a condensed, machine-readable summary of the site’s content. Two files:

  • /llms.txt — short, table-of-contents style. Top-level pages, brief descriptions.
  • /llms-full.txt — long-form. The actual content for AI ingestion.

The pitch: LLMs that crawl your site to answer user questions get a curated index instead of having to crawl every page.

In practice, it never became a real standard. Anthropic, OpenAI, and Perplexity have never officially committed to reading these files. Google has now publicly said it doesn’t either.

But several smaller AI engines and developer-focused indexers do consume llms.txt when present. And the cost to maintain a properly designed one is approximately zero. So the cost/benefit math is interesting.

My implementation in Next.js 16 App Router

Three files. Total: about 90 lines.

Step 1: a renderer that pulls content from your CMS

I keep mine in lib/llms.ts. It reads from Sanity, but the same pattern works with anything: Markdown files, MDX, a database, a JSON config.

// lib/llms.ts
import { getAllBlogPosts, getAllResources } from '@/lib/sanity'

const SITE_URL = 'https://example.com'

function resourceCategory(slug: string): 'permit' | 'comparison' | 'glossary' | 'general' {
  if (slug.startsWith('building-permit-guide-')) return 'permit'
  if (slug.includes('-vs-')) return 'comparison'
  if (slug.startsWith('what-is-')) return 'glossary'
  return 'general'
}

export async function renderLlmsTxt(): Promise<string> {
  const posts = await getAllBlogPosts()
  const resources = await getAllResources()

  const lines: string[] = []
  lines.push('# Example Company')
  lines.push('')
  lines.push('> Toronto-based contractor specializing in framing, drywall, and insulation.')
  lines.push('')
  lines.push('## Core Pages')
  lines.push('- [Home](https://example.com)')
  lines.push('- [Services](https://example.com/services)')
  lines.push('- [About](https://example.com/about)')
  lines.push('- [Contact](https://example.com/contact-us)')
  lines.push('')

  const permits = resources.filter(r => resourceCategory(r.slug.current) === 'permit')
  const comparisons = resources.filter(r => resourceCategory(r.slug.current) === 'comparison')
  const glossary = resources.filter(r => resourceCategory(r.slug.current) === 'glossary')

  if (permits.length) {
    lines.push('## Building Permit Guides')
    for (const r of permits) {
      lines.push(`- [${r.title}](${SITE_URL}/resources/${r.slug.current})`)
    }
    lines.push('')
  }

  if (comparisons.length) {
    lines.push('## Comparison Pages')
    for (const r of comparisons) {
      lines.push(`- [${r.title}](${SITE_URL}/resources/${r.slug.current})`)
    }
    lines.push('')
  }

  if (glossary.length) {
    lines.push('## Glossary')
    for (const r of glossary) {
      lines.push(`- [${r.title}](${SITE_URL}/resources/${r.slug.current})`)
    }
    lines.push('')
  }

  if (posts.length) {
    lines.push('## Blog')
    for (const p of posts) {
      lines.push(`- [${p.title}](${SITE_URL}/blog/${p.slug.current})`)
    }
  }

  return lines.join('n')
}

export async function renderLlmsFullTxt(): Promise<string> {
  // Same shape as renderLlmsTxt, but inline the actual body content per
  // resource/post. Pull body from your CMS, convert to plaintext, append
  // under each section header.
  // omitted for brevity
}

The category split is my preference. The spec is loose. What matters is that a machine reading the file gets a clean hierarchical view of your site.

Step 2: the route handlers

Next.js 16 App Router treats files inside /app as routes. Drop a route.ts inside any folder named for your URL path:

// app/llms.txt/route.ts
import { renderLlmsTxt } from '@/lib/llms'

export const revalidate = 3600 // 1 hour cache

export async function GET() {
  const body = await renderLlmsTxt()
  return new Response(body, {
    headers: { 'content-type': 'text/plain; charset=utf-8' },
  })
}
// app/llms-full.txt/route.ts
import { renderLlmsFullTxt } from '@/lib/llms'

export const revalidate = 3600

export async function GET() {
  const body = await renderLlmsFullTxt()
  return new Response(body, {
    headers: { 'content-type': 'text/plain; charset=utf-8' },
  })
}

The revalidate = 3600 line is the key. It tells Vercel/Next.js to serve a cached version for an hour, then regenerate on the next request. If you publish 10 blog posts a day, the file picks them up within 60 minutes. If you publish once a week, it picks them up within an hour of publishing. No build step required.

Step 3: deploy and verify

curl https://example.com/llms.txt

Should return your generated markdown-flavored text in seconds.

That’s it. Total code: about 90 lines. Total time: 40 minutes if you’ve used Next.js before.

Then Google said don’t bother

Google’s AI optimization guide (published this month) is explicit:

Don’t create llms.txt files and other “special” markup.

The reasoning, per Google: their AI features (AI Overviews, AI Mode) ingest the same content humans see. They crawl pages, parse the rendered HTML, and synthesize. They don’t read llms.txt. Creating one is “unnecessary effort.”

That’s an honest position. Google isn’t penalizing you for having an llms.txt. They’re telling you it’s wasted work from their perspective.

But Google isn’t the only AI engine.

Why I’m keeping mine anyway

Four reasons.

1. The maintenance cost is zero

Because the file is dynamic and pulls from the same content source as the rest of the site, it updates itself. There’s no separate workflow to maintain, no monthly chore, no risk of going stale. The code sat in the repo for two weeks with zero attention required. The next time I add a blog post or resource page, the file picks it up within an hour.

If maintenance cost were measured in minutes per month, llms.txt would be at zero. There’s nothing to abandon.

2. Not every AI engine has spoken

Perplexity, ChatGPT, Claude, and several smaller AI search products have not officially said whether they read llms.txt. Some open-source RAG indexers do. Some agent frameworks default to checking for it.

If even one of these tools reads my llms.txt and produces a citation that a human user clicks, the file paid for itself. The opportunity cost of having it is approximately the bytes Vercel serves on the rare requests that hit the endpoint.

3. It functions as a structured fallback

The llms.txt is one of the cleanest, most human-readable summaries of my site that exists anywhere. When someone asks me for an overview of my site’s content, I can paste the llms.txt into a chat and have an instant brief. It’s a free side effect of building it.

4. Building it was a useful exercise

Going through the exercise of categorizing every page, deciding what’s important, and giving each section a clean summary is exactly the kind of content audit most sites should do anyway. The output (the llms.txt file) is the artifact. The thinking is the value.

When to skip it

If your site is purely commerce, your content is highly dynamic (millions of product pages), or your content lives mostly behind login, llms.txt has less value. AI engines aren’t going to ingest your product catalog from a flat text file.

If you’re a content site, a docs site, a portfolio, an editorial publication, or anything where the page-level content matters and the URL structure has meaning, llms.txt is worth the 40 minutes.

Working example

You can see the live output at:

Both regenerate every hour. Both pull from the same Sanity CMS that drives the rest of the site. Total runtime memory cost: indistinguishable from zero. Pageviews: low but non-zero.

The bigger point

Google publishing guidance that says “don’t bother with X” is not the same as Google penalizing X. Sometimes Google is telling you the optimal allocation of your effort. Sometimes you should agree. Sometimes you should keep doing X because the cost is zero and the upside, while small, is nonzero.

llms.txt is in the second bucket. Build it once, let it run, ignore the file for six months, see what happens.

If in 18 months Google publishes “we now use llms.txt to inform AI Overviews,” you’ll be glad you left it running. If they don’t, the file cost you 40 minutes and approximately zero ongoing attention.

The optimal play with low-cost, low-confidence bets is to make a lot of them and let outcomes resolve themselves.

Build the llms.txt.

AWS Summit Seoul 2026: Korean Enterprises And Agentic AI

Amazon

Over the last few years, people have been asking the same question about AI: with so much money going into models, GPUs, and data centers, when will it pay off? Earnings calls and analyst reports have often mentioned a possible bubble, and companies that tried generative-AI pilots in 2024 have been waiting to see real production results.

At AWS Summit Seoul 2026, Samsung Electronics, Yogiyo, and Yanolja presented production-oriented agentic-AI/AIOps cases, while KB Kookmin Bank presented a production-scale KBaaS API-infrastructure modernization case. Together, the sessions showed how Korean enterprises are applying AI-era cloud architecture to operations, development, and embedded finance. Here’s a summary of how the event was organized, what the enterprise sessions showed, which AWS tools were most common, and the key patterns you can apply to your own plans.

The shift the day was framed around

AWS Korea CEO Ham Ki-ho opened the event by outlining three stages: Generative AI, Agentic AI, and Physical AI. He described Agentic AI as the active phase, where large language models act as reasoning engines that plan, use tools, and take action, instead of just answering prompts. Physical AI was presented as the next step, with a new Physical AI Frontier Program for Korean robotics, AI-chip, and manufacturing companies. This program will support everything from data collection to edge inference and help with global expansion.

AWS CFO Jon Felton announced a cumulative ₩12.6 trillion investment plan in Korea by 2031, described publicly as the largest-ever investment in Korea by a global cloud provider, with an estimated ₩15.06 trillion contribution to Korea’s GDP between 2023 and 2027. The Industry Day talks that followed showed how this commitment will play out in practice.

Amazon's internal AI evolution presented by AWS — from an LLM-powered search assistant in 2023 to a planning-engine architecture and MCP-driven tooling in 2025

The keynote also highlighted the main agentic tools AWS featured at the event, with Vice President Jason Bennett explaining each one:

  • Kiro: a new agentic IDE for software development, described on stage as a peer to Claude Code and Copilot-style coding assistants
  • Amazon Quick Suite: an agentic AI workspace for finding insights, conducting research, automating tasks, visualizing data, and taking actions across apps
  • AWS Transform and AWS Transform Custom: agentic modernization tools for mainframe, VMware, Windows, and legacy-code modernization, including version upgrades, runtime migrations, language translations, and architecture changes

What the enterprise talks actually showed

Across the agentic-AI sessions, a pattern emerged, but it was not universal. Samsung and Yanolja both used a supervisor or core-agent structure that delegates work to specialist agents. Yogiyo showed a Bedrock AgentCore-based AIOps workflow connected to operational data and tool functions. KBaaS was different: an EKS-based API platform and gateway modernization for embedded finance.

Samsung Electronics' AgentCore-based AIOps architecture: a Supervisor Agent orchestrates Domain Agents (DR, Incident, Change, Database, FinOps), each composed of Task Agents that call AWS resources directly

The numbers made it clear these were real deployments, not just experiments. Samsung Electronics used Samsung Account, which supports 2.1 billion users, over 50 services, more than 2.7 million requests per second, and 200,000 transactions per second across four regions on EKS with over 70 namespaces. Samsung set Day-1 AIOps goals including 90%+ MTTR reduction, 99% incident detection within 10 minutes, and reducing human-in-the-loop operational work below 20%, as part of a roadmap toward ‘Toil 0% / Human First.’ KB Kookmin Bank’s KBaaS platform now handles about 1,800 APIs and 200 million calls per day after switching from a third-party API gateway to their own on AWS EKS. Yogiyo showed how they moved from checking multiple consoles and logs during incidents to using an AgentCore-based AIOps loop, which brings metric observation, correlation analysis, change-history comparison, and RCA grounding into one workflow. Yanolja shared the most technical details, describing how their domain-specialist agents for DevOps and SRE are managed by a Core Agent on Bedrock AgentCore Runtime, using Strands Agent as the SDK and end-to-end authentication.

Yanolja's three Strands Agents multi-agent patterns:

Samsung, Yogiyo, and Yanolja all centered their agentic-AI cases on AIOps or infrastructure operations rather than customer-facing copilots. KB Kookmin Bank’s case showed a different but related production pattern: modernizing a high-volume API platform on EKS for embedded finance.

On the development side, the counterpart is AI-DLC (AI-Driven Development Lifecycle), which is AWS’s approach to AI-led development with humans checking at validation and final approval. Samsung saw a 70% reduction in lead time using this method, and LG Electronics’ MS division reported double the productivity. The main idea is to separate intent from execution: humans decide what should happen and check the results, while agents handle the steps in between.

The AWS-native stack that recurred

AWS AI Factories — the full agentic stack as presented in the AWS Summit Seoul 2026 keynote: Applications and Agents (Kiro, Amazon Quick Suite, AWS Transform), Agent Builders (Amazon Nova Act, Strands Agents), Amazon Bedrock (Models, Capabilities, AgentCore with Runtime / Identity / Memory / Observability / Policy), and the infrastructure layer beneath

A few key components showed up again and again in the enterprise sessions:

  • Amazon Bedrock AgentCore appeared across Samsung, Yogiyo, and Yanolja. Yanolja explicitly presented Bedrock AgentCore Runtime with Strands Agent and authentication. Yogiyo showed an AIOps architecture using Amazon Bedrock AgentCore with runtime, memory, gateway, and MCP tool functions. Samsung showed an AgentCore-based AIOps architecture with Supervisor, Domain, and Task agents.
  • Kiro was used as the agentic IDE, and Samsung included it in their toolset along with Amazon Quick Suite and Bedrock AgentCore.
  • Amazon EKS was the hosting platform for both Samsung Account and KBaaS, the two cases where the host was clearly specified.

The themes worth taking home

Several patterns stood out during the day. First, the supervisor pattern appeared twice independently. Samsung and Yanolja reaching the same structure without coordination is a strong signal. Second, in three of the four cases (Samsung, Yogiyo, Yanolja), the entry point was AIOps or infrastructure operations rather than customer-facing copilots. KB Kookmin Bank instead modernized its API platform on EKS for embedded finance. Third, humans are intentionally kept in the loop. Datadog’s session made this clear, stating that sovereignty and judgment remain with people, while agents handle execution via the Datadog AI Agent Builder. Samsung’s AI-DLC approach on the development side followed the same principle. Fourth, infrastructure needs to catch up. GS Neotek’s session highlighted that the real GPU issue in agent workloads is not a shortage but poor utilization, excessive idle time, and over-allocation. They suggested using Dynamic Resource Allocation (DRA) on EKS as a next-generation operations model that considers workload needs, sharing policies, and topology.

GS Neotek's DRA (Dynamic Resource Allocation) core structure: a three-stage flow of Advertise (ResourceSlice) → Define & Request (DeviceClass + Claim) → Match (Attribute-aware Matching), letting workloads request GPUs by capability rather than by count

Selection Sort Explained Simply — Algorithm, Code & Complexity

Selection Sort’s superpower: fewest swaps of any simple sorting algorithm — at most n-1 total. In systems where writes are expensive, this matters.

🧠 The Core Idea

Every pass: scan the unsorted region, find the minimum, swap it to the front.

Analogy: Sorting 30 answer sheets by roll number. Scan all, find Roll No. 1, pull it. Scan remaining, find Roll No. 2. Repeat.

📋 Example: [64, 25, 12, 22, 11]

Pass Min Result
1 11 [11, 25, 12, 22, 64]
2 12 [11, 12, 25, 22, 64]
3 22 [11, 12, 22, 25, 64]
4 25 [11, 12, 22, 25, 64] ✅

5 elements → 4 passes → only 2 actual swaps.

💻 JavaScript

function selectionSort(arr) {
  const n = arr.length;
  for (let i = 0; i < n - 1; i++) {
    let minIdx = i;
    for (let j = i + 1; j < n; j++) {
      if (arr[j] < arr[minIdx]) minIdx = j;
    }
    if (minIdx !== i) [arr[i], arr[minIdx]] = [arr[minIdx], arr[i]];
  }
  return arr;
}

⏱ Complexity

Case Time Space Stable Max Swaps
All cases O(n²) O(1) ❌ n-1

🆚 vs Bubble Sort

Factor Selection Bubble
Swaps n-1 max ✅ Up to n²/2 ❌
Stable ❌ No ✅ Yes

Part 8 of the Bitveen DSA Series. Originally published at bitveen.com

Does AI Know How Many Tokens It Is Burning

The strange thing about the modern AI bill is that it looks precise while the work behind it feels mysterious. A user types a short request, a model thinks through a long hidden path, tools are called, context is loaded, cached text may be reused, and the final answer arrives as if it were a single clean event. The invoice later describes the event in tokens. Input tokens, cached input tokens, output tokens, reasoning tokens, long context tokens. The language of measurement is tidy. The measured behavior is complex.

So the question matters. Does AI have an awareness of token consumption. The practical answer is almost certainly negative. A model can be prompted to write shorter answers, choose compact formats, summarize context, or stop after a budget. That remains a behavioral response rather than economic self awareness. The model is predicting text under instructions. The metering system lives around it. Token counting, caching, routing, rate limits, and billing are product and infrastructure layers built by humans. The model may talk about saving tokens, but the system decides what was consumed and what it costs.

That gap explains why token economics has become one of the least glamorous and most important parts of AI. In the first wave, the attention went to model quality. In the second wave, the attention moved to agents, context windows, voice, video, and multimodal workflows. Now the decisive question for many teams is simpler. Can the product deliver useful intelligence at a predictable unit cost.

For AI vendors, tokens are the bridge between capability and gross margin. Output tokens usually cost more than input tokens because generation is compute intensive and latency sensitive. Long reasoning can improve quality, but it also turns invisible compute into visible cost. Cached input changes the equation again. When repeated context can be reused, the provider can reduce cost and latency while keeping the customer inside the same platform. This is why pricing pages now distinguish fresh input from cached input, and why prompt caching has become a core design feature rather than a small optimization.

For cloud providers, the token is becoming a new workload unit. Traditional cloud economics was built around virtual machines, storage, bandwidth, and database operations. AI inference adds a more volatile meter. One customer request may be tiny. Another may carry a large document, a long conversation, tool outputs, and a detailed answer. GPU supply, batching, memory bandwidth, model size, quantization, and serving software all shape the cost per million tokens. Cloud platforms want to sell capacity, yet customers increasingly ask for something more concrete than capacity. They want a dependable price for intelligence delivered.

For business customers, token economics is a budgeting problem and a product design problem at the same time. A support chatbot that reads the entire customer history on every turn can become expensive fast. A coding agent that keeps every file, tool result, and prior message in context may feel magical during a demo and painful in production. A research assistant that produces long reports may create value, but only if the organization understands how much context it used, how much reasoning it triggered, and how often the same material could have been cached.

The best enterprise teams are beginning to treat tokens like inventory. They ask which context is essential, which context can be retrieved only when needed, which instructions are stable enough to cache, and which tasks justify a stronger model. They build dashboards that show cost by workflow, department, customer, and outcome. They test small models for narrow tasks and reserve frontier models for judgment heavy work. They also redesign user experiences so people can choose depth when depth matters, instead of making every request behave like a full investigation.

For consumers, token economics is usually hidden behind subscriptions and usage caps. Its relevance remains. When a chat product becomes slower, when image generation gets rationed, when voice mode is limited, or when a long conversation suddenly asks the user to start fresh, token economics is often nearby. The consumer feels it as friction. The provider experiences it as margin pressure. The model experiences none of it as a conscious concern.

This is where the consciousness question becomes useful. If we imagine the model as an aware worker, we may expect it to manage cost like a human employee watching a budget. That expectation leads to disappointment. A more accurate mental model is a powerful engine connected to meters, governors, caches, and pricing rules. The engine can follow instructions about brevity and structure. The surrounding system must manage the money.

The real opportunity is to design the surrounding system well. A useful AI product should know when to compress context, when to retrieve fresh evidence, when to ask a clarifying question, when to use a smaller model, when to stop generating, and when a richer answer is worth the extra cost. This belongs to architecture, and it is also where durable advantages will appear.

Practical workflows already show the pattern. A researcher may draft analysis in ChatGPT or Gemini, then use Miss Formula when equations or formula images need to become clean editable math. When charts and paper figures generated by AI need to move into publication or slide production, Editable Figure can convert AI generated paper figures into editable vector figure formats. The strongest workflow spends tokens with intention and turns each token into a reusable artifact.

That last phrase is the heart of token economics. Tokens function as both a billable unit and a design pressure. They force vendors to compete on inference efficiency, cloud providers to expose clearer cost models, businesses to measure value per workflow, and consumers to notice the limits of abundance. AI may lack awareness that it is burning tokens. The teams building around AI must know better.

Selling Software in Countries PayPal Can’t Reach – A Cautionary Tale of Crypto and Custom Solutions

The Problem We Were Actually Solving

Our customers were based in regions where popular payment gateways like Stripe and PayPal were either blocked or heavily restricted. We needed a solution that would allow us to process payments from these countries without breaking a sweat. However, integrating a reliable alternative proved to be a significant challenge.

What We Tried First (And Why It Failed)

Initially, we tried using the more ‘permissive’ Stripe and PayPal, despite knowing they’d eventually fail. We implemented the usual checks, like IP blocking and payment method whitelisting, in hopes that these would be enough to bypass the restrictions. However, this was a case of wishful thinking, and we soon found ourselves dealing with a myriad of declined payments, error messages (e.g., “Stripe Invalid Request” and “PayPal Connection Timed Out”), and angry customers.

The Architecture Decision

We decided to pivot and explore crypto as a viable alternative. Setting up our own crypto-based payment processing system was no easy feat, but it allowed us to sidestep the country-specific restrictions imposed by traditional payment processors. We integrated with CoinGate to process payments directly into our platform, which included handling wallet management, deposit and withdrawal limits, and fiat-to-crypto conversion.

This solution required us to implement additional checks and balances, such as wallet verification and transaction logging, to prevent abuse and maintain regulatory compliance. We also had to invest in educating our customer support team on crypto-related issues and handling the inevitable flood of questions and complaints.

What The Numbers Said After

In the first six months, our crypto integration processed over $200,000 worth of payments, with a successful transaction rate of 95%. We also saw a significant reduction in declined payments and customer complaints (from an average of 5 complaints per week to virtually zero). Moreover, our customer base expanded into previously inaccessible markets, resulting in a 20% increase in subscription revenue.

What I Would Do Differently

In hindsight, I would have explored custom solutions sooner, rather than relying on traditional payment processors. Crypto, although imperfect, has allowed us to scale internationally without the hassle of dealing with platform restrictions. However, our reliance on CoinGate has introduced additional complexity and costs, which might not be sustainable in the long run.

Moving forward, I’d consider implementing a hybrid solution that combines the benefits of crypto with custom-built payment processing. This would enable us to maintain regulatory compliance, reduce our reliance on third-party services, and further optimize our payment processing pipeline. The age-old lesson here is that sometimes, the best solution isn’t the one that works, but the one that allows you to adapt and evolve in the face of changing platform restrictions.

My Old MacBook Air Couldn’t Handle It — So I Used Google Colab to Train an AI#1

Introduction

I recently booted up an offline card game I used to love — and couldn’t clear the hardest difficulty anymore.

I used to be able to beat it.

That frustration sparked an idea: what if I trained an AI to help me figure it out? I had three constraints going in:

  • It had to work offline
  • I wanted to try reinforcement learning while I was at it
  • It had to be lightweight enough to run on an 8-year-old MacBook Air

After a lot of trial and error, I landed on building a custom engine in Rust and running the training on Google Colab. This article focuses on the Google Colab side of that setup.

What Is Google Colab?

Google Colab is a free Python execution environment provided by Google (this article assumes the free tier). All you need is a browser — no installation required.

What made it useful for this project:

  • Free GPU/CPU access
  • Integrates with Google Drive
  • Runs heavy workloads regardless of your local hardware

Training that would’ve been painful on an old MacBook Air ran smoothly once I moved it to Colab.

⚠️ Note: On the free tier, the session disconnects after a period of inactivity or after a maximum of 12 hours, and runtime data is reset.

What I Did

The goal was to train an AI to play an offline deck-building card game using reinforcement learning.

Here’s the overall flow:

  1. Translate the game rules and card effects into language
  2. Convert that into numerical data the AI can work with
  3. Build a custom training engine in Rust
  4. Upload the training data to Google Drive
  5. Mount Google Drive in Colab and run it

Steps 1–3 are all on the Rust side — I’ll cover those in a follow-up. This article focuses on steps 4 and 5.

Mounting Google Drive in Colab

Run the following code in a Colab cell:

from google.colab import drive
drive.mount('/content/drive')

You’ll see a prompt asking to authorize access to Google Drive. Click “Connect to Google Drive”, choose your account, and allow access. Once done, a drive/MyDrive folder will appear in the left sidebar.

After mounting, your Drive is accessible at:

/content/drive/MyDrive/

💡 You can also mount Drive without writing any code — just click the folder icon in the left sidebar and hit the “Mount Drive” button. It inserts the code automatically.

⚠️ If Google Drive’s cache is stale, updates to your Drive may not reflect in Colab. If that happens, force a remount:

drive.flush_and_unmount()
drive.mount('/content/drive', force_remount=True)

Running the Binary and Starting Training

Once Drive is mounted, you can execute the file you uploaded directly from Colab.

subprocess is Python’s standard library for calling external programs — in this case, the Rust binary:

import subprocess

result = subprocess.run(
    ['/content/drive/MyDrive/your_binary'],
    capture_output=True,
    text=True
)
print(result.stdout)

Replace your_binary with your actual filename.

💡 If you get a permission error, run this first. 0o755 grants execute permission on Linux:

import os
os.chmod('/content/drive/MyDrive/your_binary', 0o755)

Stuck? Ask Gemini

Colab has Gemini built in — just click the icon in the top right. Paste your error message directly and it’ll suggest a fix. Don’t hesitate to just dump the error and let it figure it out 😊

Closing

I covered the Google Colab basics, mounting Google Drive, and running a Rust binary — all from a browser, on hardware that couldn’t have handled the training locally.

If this was useful, the follow-up covers the reinforcement learning setup and how I represented the game state. I’ll write it if there’s interest 😊

👇 Part 2 here
(coming soon)

The Discord.js gotchas that cost me a week each (so they don’t have to cost you one)

I run an AI Discord bot builder that’s deployed 500+ live bots over the last year. The service takes a plain-English description, generates discord.js code, and ships the container to production in under 30 seconds.

That sounds clean. It is not clean.

Most of what I learned came from logs at 3am after someone’s bot stopped responding to messages, or a community went silent because of an undocumented Discord behavior. Here’s the list I wish I’d had on day one.

  1. Missing Permissions (50013) is usually about role position, not permissions

The first time I hit this I spent two hours auditing the bot’s permission integer. It was correct. The bot still couldn’t kick anyone.

The thing nobody puts in big letters: discord.js permissions are gated by role hierarchy. A bot can have the KickMembers permission and still fail to kick anyone whose top role sits above the bot’s top role.

client.on(‘interactionCreate’, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName !== ‘kick’) return;

const target = interaction.options.getMember(‘user’);
const botMember = interaction.guild.members.me;

if (target.roles.highest.position >= botMember.roles.highest.position) {
return interaction.reply({
content: “I can’t kick that user — their role is at or above mine.”,
ephemeral: true,
});
}

await target.kick(interaction.options.getString('reason') ?? 'No reason');
await interaction.reply(`Kicked ${target.user.tag}.`);

});

Fix in Discord: drag the bot’s role above the roles it needs to manage in Server Settings → Roles. This is the single most common reason a “working” bot doesn’t work.

  1. Unknown Interaction (10062) is a 3-second race

Slash commands give you exactly 3 seconds to respond. If you call any awaited DB query, third-party API, or LLM before.reply(), you’ll lose that race.

Wrong:
const result = await callLLM(prompt); // 2.4s
await interaction.reply(result); // 10062

Right:
await interaction.deferReply(); // buys you 15 minutes
const result = await callLLM(prompt);
await interaction.editReply(result);

The deferred reply pattern is one of those things you need to internalize once and then never get bit by again.

  1. Intent flags are silent killers

This one is brutal because there’s no error. Your bot connects, shows as online, registers commands, and never reads a message.

Two parts:

  1. In the Discord Developer Portal, toggle “Message Content Intent” on.
  2. In your client config, list it:

import { Client, GatewayIntentBits } from ‘discord.js’;

const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent, // ← without this, message.content is empty
GatewayIntentBits.GuildMembers,
],
});

If you skip either step, message.content arrives as an empty string and your prefix commands look broken for no apparent
reason.

  1. Reactions and edits on old messages are partial

If someone reacts to a message your bot didn’t observe being created (anything older than the bot’s session), the event payload is partial. Touching .content returns null until you fetch.

client.on(‘messageReactionAdd’, async (reaction, user) => {
if (reaction.partial) {
try { await reaction.fetch(); } catch { return; }
}
if (reaction.message.partial) {
try { await reaction.message.fetch(); } catch { return; }
}
// safe to use reaction.message.content now
});

Add the Partials config too:

import { Client, Partials } from ‘discord.js’;
new Client({
intents: […],
partials: [Partials.Message, Partials.Channel, Partials.Reaction],
});

  1. Ephemeral replies don’t behave like normal messages

You can’t fetch them with channel.messages.fetch(). You can’t add reactions. If you want to update one later, you need the original interaction token, not a message ID:

await interaction.reply({ content: ‘Loading…’, ephemeral: true });
// 10 seconds later
await interaction.editReply({ content: ‘Done.’ });

If you serialize the interaction across processes (queue, webhook handler, etc.), serialize the token, not the message
reference.

  1. Process crashes leave gateway sessions hanging

If your bot crashes hard without closing the websocket, Discord keeps that session alive on their end for a few minutes.
New deploys then count against the 1000/day session start limit, and on cold restarts you’ll see a brief window where two instances of your bot post duplicate messages.

async function shutdown(signal) {
console.log([bot] ${signal} received, closing gateway);
try { await client.destroy(); } catch {}
process.exit(0);
}
process.on(‘SIGTERM’, () => shutdown(‘SIGTERM’));
process.on(‘SIGINT’, () => shutdown(‘SIGINT’));

process.on(‘unhandledRejection’, (err) => {
console.error(‘[bot] unhandled rejection:’, err);
// don’t crash — log and continue
});
process.on(‘uncaughtException’, (err) => {
console.error(‘[bot] uncaught:’, err);
// do crash, but cleanly
shutdown(‘uncaughtException’);
});

If you’re running on a container platform that sends SIGTERM before forcibly killing, this single block saves you a
class of bugs you’d never spot.

  1. Rate limits aren’t always 429s

The REST client emits a rateLimited event for the soft cases (Discord’s per-route bucket warnings). If you log it from
day one, you get a free monitoring signal:

client.rest.on(‘rateLimited’, (info) => {
console.warn(‘[ratelimit]’, {
route: info.route,
method: info.method,
timeToReset: info.timeToReset,
limit: info.limit,
});
});

In production these almost always trace back to one bot in a 10k-member server doing something dumb in a loop. They Never show up in your error monitoring otherwise.

  1. The biggest one: most production failures aren’t bugs in your code

When you run a few hundred bots, the failure distribution shifts. Probably 30% of “the bot is broken” tickets I’ve seen trace back to:

  • The server admin moved roles around
  • The user revoked the bot’s invite
  • The bot was rate-limited because someone scripted 1000 reactions
  • Discord shipped a behavior change
  • A channel was deleted that the bot was scheduled to post in

Your bot needs to log enough that you can prove which of these happened quickly. A single structured log per important event (action attempted, guild ID, user ID, outcome, latency) gets you 80% of the way there.

I learned most of this the hard way running vibebot.gg, where users describe a Discord bot in English and the system generates and deploys discord.js code for them. The interesting failure mode in that setup is that the LLM-generated code has to handle all eight of these gotchas correctly the first time, because the user never sees the code. The patterns above are exactly what we now bake into every generated bot at the template level.

If you’re building a Discord bot from scratch, copy the snippets above directly. They’re worth a week of debugging each.