kintone 連携

kintone に定期実行はない。cli-kintone は残して、cron だけ置き換える。

kintone のトリガーはユーザー操作だけです。夜間同期も一括処理も基幹連携も、動かす仕組みを kintone の外に置く必要があります。Dagu がその仕組みです。公式の cli-kintone はそのまま使い、cron にはなかったリトライ、通知、履歴、カーソルを足します。

社内ネットワーク内で動き、kintone とオンプレ両方に届く
1 日あたりの API リクエスト上限に収まる差分同期
cron を置き換えた時点で失敗通知、リトライ、実行履歴が付く
セルフホストは無料、コネクタ単位のライセンスなし
01

kintone のトリガーは人であって時刻ではない

サイボウズの developer network が明言しています。kintone には連携処理を定期的に実行する機能がないため、実行する仕組みが別に必要です。公式の推奨は cli-kintone を Linux なら cron、Windows ならタスクスケジューラ、どちらもなければ AWS Lambda で回すことです。カスタマイズ JavaScript は誰かが画面を開いたときにしか動かないので、この用途では選択肢になりません。

  • 夜間集計も月次処理も一括更新も、外部の実行役を必要とします
  • cron が与えるのは実行だけです。リトライも通知も履歴も依存関係もありません
  • そして報告される失敗はいつも同じです。同期が止まっていたことに、利用者から苦情が来るまで誰も気づかない
02

公式ツールは残し、スケジューラーだけ替える

cli-kintone はページング、絞り込み、テーブル、添付ファイルをすでに解決しています。Dagu はこれを置き換えませんし、kintone 専用のステップも持ちません。既存のシェルスクリプトがそのままステップになり、cron に足りなかったものが一緒に付いてきます。

  • retry_policy が、一晩分の cron ジョブを落としていた一時的な API エラーを吸収します
  • mail_on.failure と handler_on.failure で、止まった同期が黙って放置されなくなります
  • max_active_runs: 1 で実行の重なりを止めます。重複レコードの典型的な原因です
アプリと添付ファイルの夜間バックアップ
# kintone-backup.yaml
schedule: "0 1 * * *"
max_active_runs: 1

env:
  - KINTONE_BASE_URL: https://example.cybozu.com
  - KINTONE_APP_ID: "42"

s3:
  bucket: corp-kintone-backup
  region: ap-northeast-1

steps:
  - id: export
    run: |
      cli-kintone record export \
        --base-url "$KINTONE_BASE_URL" \
        --app "$KINTONE_APP_ID" \
        --api-token "$KINTONE_API_TOKEN" \
        --attachments-dir ./attachments \
        > records.csv
    retry_policy:
      limit: 3
      interval_sec: 60

  - id: pack
    action: archive.create
    with:
      source: ./attachments
      destination: attachments.tar.gz
    depends: export

  - id: upload_records
    action: s3.upload
    with:
      key: kintone/app-42/records.csv
      source: records.csv
    depends: pack

  - id: upload_attachments
    action: s3.upload
    with:
      key: kintone/app-42/attachments.tar.gz
      source: attachments.tar.gz
    depends: pack

mail_on:
  failure: true
03

API 制限があるから差分同期に意味がある

kintone の API リクエストは 1 アプリあたり 1 日 1 万回までです。超過すると翌朝ストア管理者にメールが届き、超過が続くとサイボウズから連絡が入り、API 処理が停止されることもあります。10 分ごとの全件リロードはこの枠を食い潰します。前回成功時からの差分だけを取る方式なら食い潰しません。

  • Dagu は実行をまたいで残るカーソルを保存するので、各実行は前回以降に更新されたレコードだけを kintone に要求します
  • save_cursor は取り込みステップに依存しているため、取り込みが失敗するとカーソルは進まず、次の実行が同じ範囲をやり直します
  • 取得は 1 回 500 件、書き込みは 100 件、オフセットでのページングは 1 万件までです。更新日時での絞り込みが、この 3 つすべてを回避する方法です

保存した値はステップの標準出力に JSON のエンベロープとして現れるため、利用側のコマンドは .value 経由で読みます。state ステップの出力を直接参照する書き方では解決されません。

再起動をまたいで残るカーソルによる差分同期
# kintone-incremental-sync.yaml
schedule: "*/30 * * * *"
max_active_runs: 1

env:
  - KINTONE_BASE_URL: https://example.cybozu.com
  - KINTONE_APP_ID: "42"

steps:
  - id: load_cursor
    action: state.get
    output: CURSOR
    with:
      key: cursors/kintone-app-42
      default:
        updated_since: "2026-01-01T00:00:00Z"

  - id: window_start
    run: |
      printf 'now=%s\n' "$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$DAGU_OUTPUT_FILE"
    outputs:
      - name: now
    depends: load_cursor

  - id: export_changed
    run: |
      since="$(printf '%s\n' "$CURSOR" | jq -r .value.updated_since)"
      cli-kintone record export \
        --base-url "$KINTONE_BASE_URL" \
        --app "$KINTONE_APP_ID" \
        --api-token "$KINTONE_API_TOKEN" \
        --condition "更新日時 > \"$since\"" \
        > changed.csv
    depends: window_start
    retry_policy:
      limit: 3
      interval_sec: 60

  - id: load_to_core
    run: ./scripts/import-to-core.sh changed.csv
    depends: export_changed

  - id: save_cursor
    action: state.set
    with:
      key: cursors/kintone-app-42
      value:
        updated_since: "${steps.window_start.outputs.now}"
    depends: load_to_core

handler_on:
  failure:
    run: ./scripts/notify-sync-failure.sh

mail_on:
  failure: true
04

Webhook ではなくポーリングにする理由

kintone の Webhook は一見わかりやすいトリガーですが、同期の土台としては誤りです。Webhook の設定項目は URL とイベントの種類だけです。

  • リクエストヘッダーの欄がなく、署名の仕組みもないため、受け側のエンドポイントを送信元が認証できません
  • 通知は 1 分間に 60 回までで、超えた分はエラーもなく破棄されます。一括編集をすると静かにイベントを取りこぼします
  • CSV や Excel の読み込み、一括削除、一括更新の API 操作では Webhook がそもそも飛びません。最も大量のデータが動く操作こそ、イベント駆動の同期からは見えません

Webhook は単票の対話的な操作で遅延を縮めるには有効です。ポーリング設計の上に乗せる遅延改善であって、置き換えではありません。

05

承認は kintone、実行は Dagu

kintone のプロセス管理は、どのワークフローエンジンより承認が得意です。多段階承認、代理承認、条件分岐、そして非エンジニアがスマートフォンから使える画面があります。承認はそこに残してください。Dagu は承認済になったレコードを拾って実作業を行い、結果をレコードに書き戻します。

  • 承認する人は、すでに慣れているツールで作業を続けられます
  • ステップのリトライと失敗ハンドラーが実行側を受け持ちます。kintone が止まるのはまさにそこです
  • 結果をレコードに書き戻すことで、監査の証跡が一か所にまとまります
承認済レコードから実作業を行い、結果を書き戻す
# kintone-approved-provision.yaml
schedule: "*/10 * * * *"
max_active_runs: 1

env:
  - KINTONE_BASE_URL: https://example.cybozu.com
  - KINTONE_APP_ID: "77"
  - KINTONE_API_TOKEN: ${KINTONE_API_TOKEN}

steps:
  - id: fetch_approved
    action: http.request
    output: APPROVED
    with:
      method: GET
      url: ${KINTONE_BASE_URL}/k/v1/records.json
      headers:
        X-Cybozu-API-Token: ${env.KINTONE_API_TOKEN}
      query:
        app: ${KINTONE_APP_ID}
        query: 'ステータス in ("承認済") and 処理状況 in ("未処理") limit 100'
      silent: true

  - id: provision
    run: ./scripts/provision-accounts.sh "$APPROVED"
    depends: fetch_approved
    retry_policy:
      limit: 2
      interval_sec: 120

  - id: write_back
    run: ./scripts/mark-records-done.sh
    depends: provision

handler_on:
  failure:
    run: ./scripts/notify-provision-failure.sh

mail_on:
  failure: true
06

kintone が届かない先に届かせる

kintone とオンプレの ERP や生産管理をつなぐときの障壁は、たいていセキュリティとクライアントライセンスの費用です。社内ネットワークの中で動く単一バイナリなら、その両方を回避できます。kintone へは外向きの HTTPS、それ以外へはローカルからのアクセスで、受信側のファイアウォールを開ける必要がありません。

  • 常駐エージェントを入れずに、SSH でオンプレのホストを実行します
  • 認証情報はワークフロー側で宣言し、実行ログでは伏字になります。周囲の環境変数任せにしません
  • ステップは制御された環境で動くため、スクリプトが必要とするものは宣言が要ります。ホストから紛れ込むことがありません

sql ステップが対応するのは PostgreSQL と SQLite です。Oracle や SQL Server の基幹システムは、sqlplus や sqlcmd といった純正クライアントをコマンドステップとして実行して扱います。

07

商用ツールのほうが適している場合

Dagu は自分たちで運用するスケジューラーです。それが正しい選択になるチームと、ならないチームがあります。

  • サーバーを持つ担当者が置けないなら、ホスト型の連携製品を選ぶほうが正直です
  • 連携を作るのが非エンジニアなら、krewData や EAI 製品のような GUI のツールのほうが YAML より早く立ち上がります
  • 日本語対応の SLA 付き保守契約が必要なら、Dagu にあるのはコミュニティ Discord と有償プランのメールサポートで、同じものではありません

FAQ

導入前によくある質問

kintone 専用のステップやプラグインはありますか?

ありません。Dagu は公式の cli-kintone コマンド、または X-Cybozu-API-Token ヘッダーを付けた REST API への HTTP ステップで kintone を操作します。これは意図的な選択です。cli-kintone がすでにページングや添付ファイル、テーブル項目を解決しており、作り直してもサイボウズのリリースに追従し続ける層が増えるだけだからです。

API リクエスト上限に収めるにはどうすればいいですか?

全件リロードをやめて差分にしてください。前回成功時の時刻を保存し、それ以降に更新されたレコードだけを 500 件ずつ取得します。実行間隔を広げるのも有効です。30 分ごとのジョブは 5 分ごとの 6 分の 1 のリクエスト数で済み、基幹連携のほとんどの用途では体感差がありません。

レコードが更新されたときに kintone から Dagu を直接呼べますか?

安全には呼べません。kintone の Webhook は URL とペイロードだけを送り、リクエストヘッダーも署名もありません。一方 Dagu の Webhook トリガーは Bearer トークンを要求します。社内の Dagu に到達させるにはトンネルも必要です。スケジュールでのポーリングならどちらの問題も起きませんし、CSV 読み込みや一括操作では Webhook がそもそも飛ばない以上、設計としてもポーリングのほうが正確です。

同期が途中で失敗したらどうなりますか?

カーソルは取り込みステップが成功した後にだけ進むため、失敗した実行ではカーソルはそのまま残り、次の実行が同じ範囲をやり直します。max_active_runs を 1 にしておけば、失敗はデータの欠落や重複ではなく遅延になります。

基幹側が Oracle や SQL Server でも使えますか?

純正クライアント経由で使えます。組み込みの sql ステップが対応するのは PostgreSQL と SQLite なので、Oracle や SQL Server は sqlplus や sqlcmd を通常のコマンドステップとして、ローカルまたは SSH 経由で実行して扱います。このページの他の内容はそのまま当てはまります。

次のステップ

まず 1 本から始める。

Dagu を入れて、いま cron で動いているスクリプトを 1 本だけ YAML に移し、実際の実行履歴で判断してください。