技術 約13分で読めます

WordPress 7.0直前でAI基盤は残りリアルタイム共同編集は見送り

いけさん目次

WordPress 7.0は、2026年5月20日リリース予定のまま進んでいる。
ただし「7.0の目玉」として見られていたリアルタイム共同編集は、5月8日にリリース対象から外れた。

残った主役は、AI Client、Connectors API、PHPだけで登録できるブロック、エディタまわりの段階的な整理だ。
WordPress 7.0は「Google Docsみたいな共同編集が来る版」ではなく、「AI連携とブロック開発の足場を入れる版」として見たほうが近い。

5月20日予定だがRC3は実質やり直しベータだった

WordPress 7.0の開発ページでは、当初の一般公開日は2026年4月9日だった。
その後、リアルタイム共同編集の実装に関するテストフィードバックを受けて延期され、現在の予定は2026年5月20日になっている。

ややこしいのは、5月8日のRC3が名前だけRCで、扱いとしては「new Beta 1」だった点だ。
更新後のリリーススケジュールでも、RC3とRC4の扱いは途中で修正されている。
5月12日時点では、5月14日にRC4、5月19日にドライランと24時間コードフリーズ、5月20日に一般公開という並びだ。

The Path Forward for WordPress 7.0では、延期中の扱いもかなり絞られていた。
新機能や機能強化は入れず、現在のリリースサイクルで入ったバグの修正を中心にする。
例外として扱われたのが、リアルタイム共同編集の安定化と、Connectors管理画面の体験改善だった。

AI Clientは「AIを書く機能」ではなく共通呼び出し層

AI Clientの開発者向けノートを見ると、WordPress 7.0が入れるのはプラグインやテーマがAIプロバイダーを呼ぶための共通PHP APIだ。

内部は2層になっている。
ひとつはCoreに同梱されるプロバイダー非依存のPHP AI Client。
もうひとつは、WordPressの流儀に合わせた wp_ai_client_prompt() などのラッパーだ。

プラグイン側は、テキスト生成、画像生成、音声、動画などが使えるかを is_supported_for_text_generation() のようなメソッドで確認できる。
公式ノートでも、WordPress 7.0が入っているだけでAI機能が使えると決め打ちするな、と書かれている。
APIキーもモデルも、実際には後述のConnectorsやプロバイダープラグイン側に依存する。

この位置づけは、前に書いたACF 6.8がWordPressをAIエージェントの操作対象にするとつながる。
ACF 6.8はWordPress 6.9のAbilities APIを使って、カスタム投稿タイプやフィールドグループ操作をAIエージェントから見える形にした。
7.0のAI Clientは、その手前にある「AIプロバイダーをどう呼ぶか」の層をCore側に寄せる。

Connectors APIでAPIキー管理をCoreへ寄せる

Connectors APIは、外部サービスとの接続情報を登録・管理する仕組みだ。
最初の焦点はAIプロバイダーで、WordPress 7.0にはAnthropic、Google、OpenAIの3つのfeatured connectorが入る。
管理画面には Settings → Connectors が追加され、APIキーやプロバイダー発見を標準化する。

Connectorは、表示名、説明、ロゴ、認証設定、関連プラグイン情報を持つ。
プロバイダープラグインがWP AI Clientへ統合していれば、Connectors API側で自動発見される。
プラグイン作者が同じようなAPIキー保存UIを何度も作る状態を減らす狙いだ。

ここはWordPressらしい。
Coreが巨大なAI機能を直接持つのではなく、プラグインがぶら下がるための共通レジストリと設定面を先に作る。
Abilities API、AI Client、Connectors APIが揃うと、WordPressは「AIが直接理解して呼び出せるCMS」に寄っていく。

PHPだけで簡単なブロックを登録できる

開発者向けで一番わかりやすい差分は、PHP-only block registrationだ。
register_block_type()supports.autoRegister を付け、render_callback を渡すと、JavaScript登録なしで簡単なサーバーサイドレンダリングブロックをエディタに出せる。

これはGutenbergのブロック開発を全部PHPに戻す話ではない。
公式ノートでも、インタラクティブなブロックや高機能な編集体験を置き換えるものではないとされている。
ただ、クラシックテーマやサーバー主導のサイトで「小さな表示部品をブロック化したい」だけなら、ビルド環境を組まずに済む。

属性の型が対応していれば、Inspector Controlsの編集UIも自動生成される。
古いWordPress案件で、ショートコードを少しずつブロックに移したい場面にはかなり合う。

エディタのiframe化は7.0で強制されない

Iframed Editor Changes in WordPress 7.0も、地味だがプラグイン作者には見逃せない変更だ。
現在、投稿エディタは登録済みブロック全体のAPIバージョンを見てiframe化するかを判断している。
7.0では、投稿内に実際に挿入されているブロックだけを見るようになる。

全ブロックがBlock API v3以上なら投稿エディタはiframe化され、古いブロックが入っていればiframeは外れる。
「インストールされているだけの古いブロック」が投稿エディタ全体のiframe化を止める状況が減る。

一方で、WordPress 7.0本体ではiframeを強制しない。
Gutenbergプラグイン側ではクラシックテーマでも強制する方向でテストを集めるが、Core本体は段階的な移行に留める。
古いブロックを抱えるサイトでは、この差が大きい。

新しいブロックは入るが重心はAI連携側

WordPress 7.0のブロック面では、Accordion、Breadcrumbs、Icon、Math、Post Time to Read、Term Queryなどが追加対象として整理されている。
7.0版のブロック別デザインツール一覧では、Poetryブロックへの名称変更や、Accordion系の子ブロックも確認できる。

サイト制作者には分かりやすい差分だが、7.0の重心はAI基盤と外部連携側にある。
WordPress 6.9でAbilities API、Block Bindings、DataViewsまわりが進み、7.0でAI ClientとConnectorsが重なる。
ブロック追加より、外部サービス、AIプロバイダー、CMS内の操作能力をどうつなぐかのほうが大きい。

この流れを見ると、CloudflareのEmDashのような「AIやMCPを前提にしたCMS」とWordPressが同じ土俵へ寄ってきた感じがある。
ただしWordPressは既存プラグインとホスティング環境を背負っているので、急に全部を作り替えるわけにはいかない。
7.0の延期と機能見送りは、その制約がそのまま出た。

リアルタイム共同編集は7.0から外れた

5月8日、Real-time collaboration will not ship in WordPress 7.0が公開された。
Matt Mullenwegが、現行アプローチをCoreに入れるには十分堅牢ではないと判断したという内容だ。
理由として挙げられているのは、surface area、race conditions、server load、memory efficiency、fuzz testingで繰り返し見つかったバグ。

リアルタイム共同編集は、複数ユーザーが同じ投稿を同時編集するための機能だった。
Google Docs的な体験をWordPressのブロックエディタへ持ち込むもので、7.0の目玉としてかなり期待されていた。

外れた直接の原因はホスティング環境の多様さだ。
同期データをどこへ保存するか、HTTP pollingでどのホスティング環境まで耐えられるか、オブジェクトキャッシュがない共用サーバーでどう崩れるか。
UIの進捗ではなく、WordPress特有の広い実行環境がネックになった。

同日に出たReal Time Collaborationの性能テスト分析では、4つの保存戦略が比較されている。
RC2時点の post-meta、専用テーブル、post metaとtransientsの組み合わせ、専用テーブルとtransientsの組み合わせだ。

8つのホスティング環境で集めた結果では、custom-table-with-transients が推奨になった。
平均ではRC2の post-meta 実装より約52%速く、純粋な専用テーブル方式も約37%速かった。
それでも7.0へ入れる判断にはならず、今後の反復に回された。

この数字が出ているのに見送ったのは、わりと健全な判断に見える。
WordPressは共用サーバーから大規模マネージド環境まで動くので、最速の環境だけで勝っても足りない。
共同編集は壊れた時の被害が投稿データに直撃する。

5月20日に入れるなら「共同編集目的」ではない

WordPress 7.0を5月20日に本番へ入れる理由があるとしたら、AI ClientやConnectors APIを前提にしたプラグイン検証、PHP-only block registration、エディタiframe化の挙動確認あたりになる。
リアルタイム共同編集を目当てに待っていたサイトは、7.0本体では何も始まらない。

既存サイトで見る場所は、使っているブロックがBlock API v3へ寄っているか、AIプロバイダー連携プラグインがConnectors APIを使い始めるか、APIキー管理がどこへ移るか。
ACFやMCP AdapterのようにWordPressをAIエージェントの操作対象にする構成では、Abilities APIだけでなくAI ClientとConnectorsの権限境界も確認対象になる。

wp_ai_client_prompt() のコード例

AI Clientの起点は wp_ai_client_prompt() で、fluent builderパターンで設定を積む。
テキスト生成なら generate_text()、画像なら generate_image() で終端する。

$text = wp_ai_client_prompt( 'WordPressのキャッシュ戦略を要約して' )
    ->using_temperature( 0.7 )
    ->generate_text();

if ( is_wp_error( $text ) ) {
    return;
}

echo wp_kses_post( $text );

プラグイン側でAI機能のUIを出すかどうかは is_supported_for_text_generation() で分岐する。
WordPress 7.0が入っているだけではAI機能は動かない。
プロバイダープラグインとAPIキーが揃って初めて true を返す。

$builder = wp_ai_client_prompt( 'test' );

if ( $builder->is_supported_for_text_generation() ) {
    // テキスト生成UIを表示
}

is_supported_for_image_generation()is_supported_for_speech_generation() なども用意されていて、どのモダリティが使えるかはプロバイダー依存になる。

JSON形式で構造化データを返させたい場合は as_json_response() にスキーマを渡す。

$schema = array(
    'type'  => 'array',
    'items' => array(
        'type'       => 'object',
        'properties' => array(
            'plugin_name' => array( 'type' => 'string' ),
            'category'    => array( 'type' => 'string' ),
        ),
        'required' => array( 'plugin_name', 'category' ),
    ),
);

$json = wp_ai_client_prompt( 'プラグイン5つとカテゴリを挙げて' )
    ->as_json_response( $schema )
    ->generate_text();

REST APIのコールバックに組み込む場合はこうなる。

function my_rest_callback( WP_REST_Request $request ) {
    $result = wp_ai_client_prompt( $request->get_param( 'prompt' ) )
        ->generate_text_result();

    return rest_ensure_response( $result );
}

generate_text_result()GenerativeAiResult オブジェクトを返す。
getTokenUsage() でトークン消費量、getProviderMetadata() でプロバイダー情報が取れる。

Connectors経由で複数プロバイダーが登録されている環境では、モデルの優先順位も指定できる。

$result = wp_ai_client_prompt( '活版印刷の歴史を要約して' )
    ->using_model_preference(
        'claude-sonnet-4-6',
        'gemini-3.1-pro-preview',
        'gpt-5.4'
    )
    ->generate_text_result();

管理者以外のプロンプト実行をブロックするフィルターフックもある。

add_filter(
    'wp_ai_client_prevent_prompt',
    function ( bool $prevent, WP_AI_Client_Prompt_Builder $builder ): bool {
        if ( ! current_user_can( 'manage_options' ) ) {
            return true;
        }
        return $prevent;
    },
    10,
    2
);

Connectors APIのプラグイン側コード

プロバイダープラグインが登録するConnectorのデータ構造はこうなっている。

array(
    'name'           => 'Anthropic',
    'description'    => 'Text generation with Claude.',
    'logo_url'       => 'https://example.com/anthropic-logo.svg',
    'type'           => 'ai_provider',
    'authentication' => array(
        'method'          => 'api_key',
        'credentials_url' => 'https://platform.claude.com/settings/keys',
        'setting_name'    => 'connectors_ai_anthropic_api_key',
    ),
    'plugin'         => array(
        'file' => 'ai-provider-for-anthropic/plugin.php',
    ),
)

テーマやプラグインからは、コネクタの有無を確認してから処理を分岐する。

if ( wp_is_connector_registered( 'anthropic' ) ) {
    $connector = wp_get_connector( 'anthropic' );
    echo $connector['name']; // 'Anthropic'
}

全登録済みコネクタを回すなら wp_get_connectors() を使う。

$connectors = wp_get_connectors();
foreach ( $connectors as $id => $connector ) {
    printf( '%s: %s', $connector['name'], $connector['description'] );
}

既存コネクタの説明文を上書きしたい場合は、wp_connectors_init アクションで一度unregisterして再登録する。

add_action( 'wp_connectors_init', function ( WP_Connector_Registry $registry ) {
    if ( $registry->is_registered( 'anthropic' ) ) {
        $connector = $registry->unregister( 'anthropic' );
        $connector['description'] = __( 'Custom description.', 'my-plugin' );
        $registry->register( 'anthropic', $connector );
    }
} );

PHP-only blockの登録コード

register_block_type()'supports' => array( 'autoRegister' => true ) を付けると、block.jsonもJavaScript登録ファイルもなしでブロックをエディタに出せる。

function my_register_php_only_blocks() {
    register_block_type(
        'my-plugin/example',
        array(
            'title'           => __( 'My Example Block', 'myplugin' ),
            'attributes'      => array(
                'title'   => array(
                    'label'   => __( 'Title', 'myplugin' ),
                    'type'    => 'string',
                    'default' => 'Hello World',
                ),
                'count'   => array(
                    'label'   => __( 'Count', 'myplugin' ),
                    'type'    => 'integer',
                    'default' => 5,
                ),
                'size'    => array(
                    'label'   => __( 'Size', 'myplugin' ),
                    'type'    => 'string',
                    'enum'    => array( 'small', 'medium', 'large' ),
                    'default' => 'medium',
                ),
            ),
            'render_callback' => function ( $attributes ) {
                return sprintf(
                    '<p>%s: %d items (%s)</p>',
                    esc_html( $attributes['title'] ),
                    $attributes['count'],
                    $attributes['size']
                );
            },
            'supports'        => array(
                'autoRegister' => true,
            ),
        )
    );
}

add_action( 'init', 'my_register_php_only_blocks' );

属性に label を付けておくとInspector Controls(サイドバーの編集パネル)が自動生成される。
対応する属性型は stringnumberintegerboolean で、enum を付ければセレクトボックスになる。
ショートコードからの移行で「表示するだけのブロック」を作りたい場面なら、この形式で足りる。

functions.phpに入れるなら

AI Clientは単体で呼ぶだけでなく、フックやショートコードに埋め込んで既存のWordPressワークフローに乗せられる。
functions.phpやプラグインファイルに書くときの実装パターンをいくつか置いておく。

投稿公開時にexcerptを自動生成

add_action( 'transition_post_status', function ( string $new, string $old, WP_Post $post ) {
    if ( 'publish' !== $new || ! empty( $post->post_excerpt ) ) {
        return;
    }

    $builder = wp_ai_client_prompt( 'test' );
    if ( ! $builder->is_supported_for_text_generation() ) {
        return;
    }

    $body = wp_strip_all_tags( $post->post_content );
    if ( mb_strlen( $body ) < 200 ) {
        return;
    }

    $excerpt = wp_ai_client_prompt(
        sprintf( "以下の記事を120文字以内で要約:\n\n%s", mb_substr( $body, 0, 3000 ) )
    )
        ->using_temperature( 0.3 )
        ->generate_text();

    if ( is_wp_error( $excerpt ) ) {
        return;
    }

    remove_action( 'transition_post_status', __FUNCTION__ );
    wp_update_post( array(
        'ID'           => $post->ID,
        'post_excerpt' => sanitize_text_field( $excerpt ),
    ) );
}, 10, 3 );

excerptが空の投稿を公開したときだけ動く。
transition_post_status を使っているのは、下書き→公開の遷移だけを捕まえたいため。
save_post だと自動保存のたびに発火してAPIコールが無駄に増える。
wp_update_post() の手前で自分のフックを外しているのは再帰防止。

ショートコードでAI要約を埋め込む

add_shortcode( 'ai_summary', function ( $atts, $content = '' ) {
    if ( empty( $content ) ) {
        return '';
    }

    $cache_key = 'ai_sum_' . md5( $content );
    $cached    = get_transient( $cache_key );
    if ( false !== $cached ) {
        return $cached;
    }

    $builder = wp_ai_client_prompt( 'test' );
    if ( ! $builder->is_supported_for_text_generation() ) {
        return wp_kses_post( $content );
    }

    $summary = wp_ai_client_prompt( "以下を3行で要約:\n\n" . $content )
        ->using_temperature( 0.3 )
        ->generate_text();

    if ( is_wp_error( $summary ) ) {
        return wp_kses_post( $content );
    }

    $html = '<div class="ai-summary">' . wp_kses_post( $summary ) . '</div>';
    set_transient( $cache_key, $html, DAY_IN_SECONDS );
    return $html;
} );

[ai_summary]長い文章[/ai_summary] で囲んだ範囲をAIに要約させて返す。
結果はtransientに1日キャッシュするので、APIコールは初回だけ。
プロバイダー未設定の環境では元のコンテンツをそのまま返すので、壊れない。

WP-Cronで既存記事をバッチ処理

既存記事にAI処理を一括でかけたい場合は wp_schedule_event() と合わせる。

add_action( 'my_ai_batch_tags', function () {
    $builder = wp_ai_client_prompt( 'test' );
    if ( ! $builder->is_supported_for_text_generation() ) {
        return;
    }

    $posts = get_posts( array(
        'post_type'      => 'post',
        'post_status'    => 'publish',
        'posts_per_page' => 5,
        'meta_query'     => array(
            array(
                'key'     => '_ai_tagged',
                'compare' => 'NOT EXISTS',
            ),
        ),
    ) );

    foreach ( $posts as $post ) {
        $body = wp_strip_all_tags( $post->post_content );

        $result = wp_ai_client_prompt(
            sprintf( "以下の記事にタグを3〜5個、カンマ区切りで返して:\n\n%s", mb_substr( $body, 0, 3000 ) )
        )
            ->using_temperature( 0.2 )
            ->generate_text();

        if ( ! is_wp_error( $result ) ) {
            $tag_array = array_map( 'trim', explode( ',', $result ) );
            wp_set_post_tags( $post->ID, $tag_array, true );
        }

        update_post_meta( $post->ID, '_ai_tagged', time() );
    }
} );

if ( ! wp_next_scheduled( 'my_ai_batch_tags' ) ) {
    wp_schedule_event( time(), 'hourly', 'my_ai_batch_tags' );
}

posts_per_page を5にしているのはAPIレートリミットとタイムアウト対策。
_ai_tagged メタで処理済みをマークして、毎時5件ずつ進める。
タグ付け以外にも、カテゴリ振り分けやdescription生成に同じ構造で応用できる。