Inside of LOVOT

GROOVE X 技術ブログ

LOVOT 3.0 アーキテクチャ移行の旅

はじめに

GROOVE X では、これまで LOVOT 初代(以下、初代)/ LOVOT 2.0(以下、2.0)をリリースし、2024年に LOVOT 3.0(以下、3.0)をリリースしました。

初代と2.0では、ハードウェアに多少の違いはあるものの、CPUボード、CPUアーキテクチャなどに大きな変更はなく、初代と2.0の両方に対し、ソフトウェア開発を継続的に実施し、OSをリリースしてきました。 初代と2.0での CPUボード は、LOVOT 本体だけではなく、Nest(巣)をあわせて3つ存在しています。

(3つの CPUボードについては 「LOVOTのOSのつくりかた」を参照)

初代と2.0 の CPUボード(コンピューター)は 3つ / LOVOTとNest(LOVOT ANATOMY より一部抜粋)

3.0では、LOVOT に NVIDIA(R) Jetson(TM) を採用し、これまで3つあったCPUボードを一つにまとめたような形となり、初代と2.0の開発コードをどのように活かすのか、また、共通化できるのか、がポイントとなりました。

続きを読む

SESSIONS 2024 に初参加してきたよ!

こんにちは、GROOVE X SWチームの Junya Fukuda です。

この記事はGROOVE X Advent Calendar 2024の17日目の記事であり、SESSIONS Advent Calendar 2024 - Adventar の 17日目の記事です。マルチポストになります。

2024年11月16日 (土) ~ 11月17日 (日) に東京お台場にある日本科学未来館で開催された SESSIONS 2024に初めて参加しました! 今回は、その様子をレポートしたいと思います。

SESSIONS 2024 at 日本科学未来館 Innovation Hall

イベントの様子 - yasuoさんの作品

SESSIONS Advent Calendar からいらしたみなさまへ

GROOVE X って?

GROOVE X は LOVOTという家族型ロボットを開発・販売している会社です。
イベント当日、会場にも(こっそり)持っていったので会場で見かけた方もいらっしゃるかもしれません。

家族型ロボット LOVOT

GROOVE Xでは、LOVOTのメカ設計をしたり、専用のLOVOTOSと呼ばれるOSを作ってGoでマイクロサービス群を動かしたり、Jetsonを搭載してRustを動かしたり、Pythonでふるまいを作ったり、国内工場で生産したり、LOVOTの専用服を作ったり、また目の描画をOpenGL(GLSL) x Rust でやっていたりします。

興味のあるトピックがありましたら、ぜひリンクをクリックしてみてください。

GROOVE X Advent Calendar からいらしたみなさまへ

SESSIONS 2024 って?

SESSIONS とはいったいどんなイベントなのでしょうか?ご存知の方もいらっしゃるかと思いますが、ご存じない方のために公式サイトから引用します。

SESSIONS 2024

プログラミングやゲームエンジン等を使って開発されたソフトウェアや自作のハードウェア等によってクリエイティブな作品を生み出す活動です! 簡単にいえば、「技術を使って生み出したおもしろいモノ」の事を指します! これにはクリエイティブコーディング・デジタルアート・デモシーンなど様々なジャンルの創作活動が含まれます!

SESSIONSとは? | SESSIONS

「デモシーン」というワードでピンときた方もいらっしゃるのではないでしょうか。 デモ (demo) は、「主に音楽を伴った美しいCGアニメーションをリアルタイムに表示するプログラム 1 」のことを指します

SESSIONSはデモシーンのイベント「デモパーティ」がルーツになっており、「SESSIONS is Beyond Demoparty」というスローガンで、デモシーンに限らず技術的に面白いものを取り扱っているイベントです。 提出された作品を上映し、来場者投票を行うコンペティション(コンポ)をはじめ、セミナーやDJ/VJイベント等さまざまなコンテンツが満載でした。

SESSIONS 2024のイベント告知ムービーを見ていただくと、イベントのイメージがわかりやすいかと思います。

www.youtube.com

ズンズンかっこいい音楽とビャーとしたかっこいい映像が大きな画面でかわるがわる見られる(ライブコーティングもある!)イベントでした!

本編 - イベントレポ

さて、本編です。
なんで参加したの?と思われる方もいらっしゃるかもしれません。参加の目的は採用と勉強です。

LOVOTの目の描画で使っているOpenGL/シェーダー関連の技術のプロフェッショナルが集まると聞いて参加しました。

リアルタイムレンダリングを行うために、シェーダーも利用しています

ただ、イベントがとても楽しくて刺激的で、気がつけば夢中になっていました。

さまざまなコンテンツ

タイムテーブルは以下になります。

SESSIONS 2024 TIMETABLE

事前に募集のあったカテゴリは以下のとおりです。オリジナル作品が上映されます。

項目 内容 詳細
Realtime Graphics -リアルタイムグラフィックス- リアルタイムレンダリング 2 される映像作品 Realtime Graphics -リアルタイムグラフィックス- | SESSIONS
Code Graphics -コードグラフィックス- Code Graphics -コードグラフィックス- | SESSIONS
Music -ミュージック- 音楽作品 Music -ミュージック- | SESSIONS
Showcase -ショーケース- 上映や技術手法などのLT Showcase -ショーケース- | SESSIONS

また上記の中にサブカテゴリ(実行ファイルの形式が64KB以下など)がありました。

さらに国内外のGLSLコーダーがライブコーディングをする「Shader Jam」、DJイベント、セミナーなども開催されました。

圧倒的な作品の数々

どのコンペも圧倒的な映像と音圧でやられました。なかでも「Realtime Graphics 」のかっこよさには度肝を抜かれました。一部をご紹介します。 (ライブデモのリンクもありますが、お使いのマシンスペックによっては見られない場合があります)

www.youtube.com

ライブデモ


www.youtube.com ライブデモ


www.youtube.com

ライブデモ


また当日の様子は、SESSIONS 2024 公式YouTubeでもご覧いただけます。

https://youtube.com/playlist?list=PLOfPKPePZaWkNdCvpnw8hjgUzjSA2nT9z

オフトピック

Musicカテゴリに参加されていた方が会場でモジュラーシンセを持ってきてくださっていました! 憧れのモジュラーシンセに触れることができ、さらに実際にモジュラーシンセを使って音楽を作っている方のお話を聞くことができて、感無量でした!(ありがとうございました!)

作ってみた

さてさてたくさんの刺激を受け、実際に手を動かしてみました。シェーダーは発表作品フォークさせていただきました。 音楽はSESSIONSで行われたmoistpeaceさんによるセミナー「プログラミングで音楽を作ろう!TidalCyclesの紹介(未経験者向け)+音・映像同期ライブシステムの紹介 by moistpeace」で紹介されていた TidalCycles を利用して、Haskellで書いています。

youtu.be

映像のコード: logo graphics from sessions
音のコード

d1 $ sound "tink:0*2" # n (irand 4)
d2 $ s "subroc3d:8 subroc3d:8 ~ subroc3d:8" # legato 0.7
d4 $ s "[~ hc:0 ~ hc:1 ~ hc:0 ~ hc:3]"
d5 $ s "[jazz:0*4]"
d6 $ s "[sugar:0]" # legato 1.0

まとめ

ただただ圧倒されるばかりの2日間でした。とても刺激的で、これからもっともっと技術を磨いていかなければと思いました。 何よりオープンなコミュニティで、初参加かつ初心者のわたしにもやさしく接してくださいました(雑に話しかけたらコンペの上位の方だったというのもちらほら!)。 運営のみなさま開催ありがとうございました!

おまけ

LOVOTにご興味のあるシェーダー使いのみなさま!ぜひカジュアルにお話させてください〜!(ad)

recruit.jobcan.jp


  1. デモシーン - Wikipedia
  2. リアルタイムレンダリングのためにGPUが必要です。作品上映用マシンスペックも公開されており、そこで動くものが条件にありました General rules -カテゴリー共通ルール- | SESSIONS リアルタイムレンダリングについてはこちら

チームの自己組織化を進める活動

こんにちは、GROOVE Xのスクラムマスターの1人、niwanoです。再び登場しました! これはGROOVE X Advent Calendar 2024の16日目の記事です。
今日は、私がスクラムマスターとして2024年度に取り組んだ「チームの自己組織化を進める」というテーマについてお話しします。

自己組織化チームとは何か?

マネジメントの父であるピーター・F・ドラッカーは、『Management Challenges for the 21st Century(日本版: 明日を支配するもの)』の中で、「これからますます多くの人たち、とくに知識労働者のほとんどが、自らをマネジメントしなければならなくなる。自らを最も貢献できるところに位置づけ、つねに成長していかなければならない。」と述べています。 この考えは、スクラムガイドに記載されている「スクラムチームは、自分たちで作業を管理できるように組織によって構成され、その権限が与えられている」という記述に通じるものがあります。

我々スクラムマスターは、"自己組織化チーム"の特徴を以下のように解釈しています。

自己組織化チームの特徴

自律性
チームメンバーはそれぞれの役割やタスクを主体的に決定し、実行します。

協調性
メンバー同士がコミュニケーションを取りながら、互いのスキルや知識を活かして課題を解決します。

適応性
状況や環境の変化に応じて、優先順位やアプローチを柔軟に変更します。

責任共有
チーム全体が成果に責任を持ちます。個人の責任だけでなく、全体としての成功を重視します。

簡単に言えば、チームが主体的に動き、すべてを自分たちで決めて進めるということです。 主体性を持つことで責任が生まれますが、同時にアジリティが高まり、多くの試行を重ねることで成功確率が向上するのではないか、という考え方です。

自己組織化チームのメリットとは?

自己組織化チームにはどんなメリットがあるでしょうか。

自己組織化チームのメリット

迅速な意思決定
チーム内で迅速に意思決定が行えるため、外部承認の遅延が減少します。

高いモチベーションと成長
自律性が高い環境では、メンバーのエンゲージメントやモチベーションが向上します。

創造性の向上
多様な視点が交わることで、革新的な解決策が生まれやすくなります。

適応力の強化
市場やプロジェクトの変化に迅速に対応できる能力が向上します。

自己組織化されたチームでは、メンバーのエンゲージメントや創造性が向上する可能性が高まります。 一方で、自己組織化が進んでいないチームを想像してみると、次のような問題が発生する可能性があります。

  • 指示待ちが多く、自主性が欠ける。
  • 自分の能力を発揮する機会が少なく、達成感が得られない。
  • 人間関係が希薄で、チーム内の信頼が不足する。

こうした状況に心当たりがある方も多いのではないでしょうか。 私自身も前職で同じような経験があり、「こういうの、あるよね」と共感する場面が少なくありませんでした。

エセ自己組織化に注意

ただし、注意が必要です。「エセ自己組織化」という状態に陥るリスクがあります。 これは、表面的には自己組織化のように見えても、実際にはその本質を欠いている状態を指します。たとえば、以下のようなケースが挙げられます。

  • 責任を互いに押し付け合う。
  • 経営陣やリーダーがチームを信頼せず、権限を十分に与えない。
  • チームが自主的に改善しようとしない。

いくら自己組織化を掲げていても、このような状況が社内で発生している場合、それは「エセ自己組織化」と呼ばざるを得ません。

誰が最初に「エセ自己組織化」という言葉を使い始めたのかはわかりませんが、非常に的確な表現ですね!

自己組織化とルールがない自由な組織は違う

自己組織化とは「なんでも自分たちチームが決めて実行できる」という状態を指しますが、これは「自由気ままに行動していい」という意味ではありません。

項目 自己組織化 ルールがない自由な組織
目的・目標 明確で共有されている 曖昧または不明確
ルール・枠組み 最低限のルールがあり柔軟性もある ルールがほとんど存在しない
協調性 チーム全体での協力が重視される 個人主義的で連携が弱い
役割分担 役割と責任が明確 役割が曖昧で責任が不明確
意思決定 メンバーに権限が委譲され効率的 混乱しやすく、遅れることが多い
成長・改善 フィードバックの仕組みがある 改善の仕組みが不十分

スタートアップ企業では「自由な組織風土」という表現をよく見かけますが、「無秩序」であって良いという事ではありません。 弊社でも自由な組織風土を大切にしていますが、それは「自由に意見を言い合える環境」を指します。 CEOも、「自由に開発していいよ、なんて一言も言ったことはない」と明言しており、まずは守・破・離の「守」をしっかり実践することが重要だと語っています。

現在、私たちは自己組織化の「守」をしっかりと実行するフェーズにあります。 この基盤を固めたうえで、さらに良い手法やアイデアが見つかったときには、自由な意見を積極的に取り入れる環境を整えるつもりです。

ハックマン権限マトリクス

ハックマン権限マトリクス(Hackman Authority Matrix)は、チームの意思決定や権限範囲を明確化するフレームワークです。 このマトリクスは、組織心理学者J.リチャード・ハックマン(J. Richard Hackman)によって提唱され、チームの自律性や自己組織化の度合いを測定する際に役立ちます。

GROOVE Xオリジナルマトリクス

このハックマン権限マトリクスに独自の要素を加えたオリジナルのマトリクスをスクラムマスターで作成しました。

オリジナルハックマン権限マトリクス

このマトリクスでは、チームが「0」から「4」の段階へ進んでいく過程を可視化しています。各段階の要件をクリアして定着すると、その称号がチームに付与されます。

0: 状態未定義
1: マネージャー主導のチーム
2: 自己管理型チーム
3: 自己設計型チーム
4: 自己統治型チーム

スクラムチームの目標は、「3. 自己設計型チーム」です。このマトリクスを活用して、チームの現在地を定期的に評価しています。

ソフトウェアチームが苦手にしていること

ソフトウェアチームの多くが、"メンバーのマイナス面の改善(ギャップフィードバック)"を苦手にしているようです。
マイナスなことは誰でも言いたくないですよね。
フィードバックカルチャーをつくる」でも紹介しましたが、メンバーの成長につながるフィードバックはギャップフィードバックと考えているので、苦手を克服してもらいたいです。

チーム転職が一般的になる時代がくる?

これは私の考えです。 自己組織化レベルの高いチームが増えることで、将来的には「チーム単位での転職」をサポートするサービスやエージェントが登場するかもしれません。

自己組織化されたチームは、プロジェクト管理やタスクの遂行効率が高いだけでなく、問題解決能力やイノベーションの創出能力も優れています。 企業にとって、すでに確立された高機能なチームを採用することは、個人を一人ずつ採用してチームを構築するよりも効率的で、即戦力としてのメリットが大きいと考えられます。

とはいえ、もし自分の会社のチームがチーム単位で転職してしまったら、大変なことになりますね!w

まとめ

スクラムマスターは、チームや組織の成長を最も実感できるポジションだと私は考えています。 このような活動に日々携われることを、本当に幸せに感じています!

これからも、チームの可能性を最大化し、組織により良い変化をもたらすために努力していきたいと思います。 スクラムマスターとしての役割を通じて、多くのチームメンバーと共に学び、成長し続けられることを楽しみにしています。

一緒に働く仲間を募集中!

いかがでしたでしょうか? 今回は、チームの自己組織化を強化する活動についてお話ししました。 これからも開発チームの自己組織化を進め、より楽しく、魅力的な開発組織を作っていきます。

弊社では、そんな開発チームで働く仲間を募集中です。 ぜひご応募ください!

recruit.jobcan.jp

(Winter '25)Account Engagement APIのメール送信機能を使ってみた ~ LOVOTの業務システムの話

この記事はGROOVE X Advent Calendar 2024の15日目の記事です qiita.com

こんにちは、LOVOTの業務システムを開発する業務を行っている尾銭です。

弊社では顧客基盤にSalesforceを利用しており、これまでMAツールとしては、Marketoを活用していたのですが、今年Account Engagement (AE) にリプレイスを実施しました。 移行の理由は割愛いたしますが、いくつかのMAツールを比較していく中で、Salesforceとの双方向データ連携が標準仕様となっているAEに価値を感じ、リプレイスすることにいたしました。

しかし、Marketoでは外部からAPIによりメール配信を行うことができたものの、AEでは、API経由でメール配信をすることができなく、一部は業務システムを改修してPardot以外からメール配信を行う運用が発生してしまっていました。

そんな状況だったので、2024年10月にようやくリリースされたAEのAPIメール送信機能は個人的にかなり嬉しかったです。 さっそく検証を行い、使用感をまとめてみました。

リリースノートはこちらをご参照ください:AE APIメール送信の変更点 help.salesforce.com

APIリファレンスはこちら:Account Engagement APIリファレンス developer.salesforce.com

AEのAPIメール送信機能でできるようになったこと

柔軟なシナリオ作成

AEでは外部の情報を元にメール配信を行う場合、AEにカスタムオブジェクトとしてデータを同期させて、同期させたデータをもとにメール配信を行う必要があります。

しかし、プロスペクトに対して関連レコードがN件存在するようなリレーションに対するシナリオ配信やコンテンツへのレコード項目の埋め込みがかなり困難という罠があります。

(実はAE移行前には気づかなかった落とし穴、、)

例えば弊社では、お客様が複数のLOVOTを契約いただいていると、お客様に対して複数の契約が紐づくことになるのですが、各契約の更新日付のNヶ月前に契約更新のお知らせを、メール本文に契約プラン名、契約更新日を埋め込んで配信することができませんでした。

しかし、外部からAPIでメール配信ができるとなると、例えばSalesforce側のフローでメール配信を行うことで高度にパーソナライズされたメール配信を簡単に行うことができるようになります。

メールコンテンツの一元管理

複数システムでお客様とのメールコミュニケーションを行っていると、お客様に配信しているコンテンツ全体を把握することが難しくなっていきます。

弊社でもコンテンツの内容を一覧のドキュメントにまとめたりしていますが、外部システムから配信しているオペレーショナルメールの一部はコンテンツの修正にエンジニア側の作業が必要になるものもあり、カスタマーサクセスチームなどで完結できていないものもあります。

しかし、外部からAPIでメール配信ができるとなると、外部システムでロジックを構築する部分はエンジニア、AEでメールコンテンツを管理するのはビジネス側と役割を分担できるようになるので、運用効率が向上すると同時に、コンテンツの整合性を保ちやすくなります。

実際に使用してみた

今回はAEでできなかったメール配信を自由度の高いSalesforceフローで行うために実装してみました。

実際にAPIを実行する処理はApexで実装する必要があります。

事前準備

まずはAPIを実行するときの認証情報を取得するために接続アプリケーションを追加します。

設定項目 設定内容
OAuthの範囲 Pardotサービスを管理のみ
コールバックURL https://login.salesforce.com/service/oauth2/token

接続アプリケーションの設定

追加した接続アプリケーションでclient_idとclient_secretを取得します。

コンシューマの詳細を管理ボタンをクリック

次はAPI実行のためのSalesforceユーザが必要になります。

ユーザライセンスはIdentityで問題ありません。

ただしPardotへのアクセス権限が必要っぽいので、権限セット、権限セットライセンスでAccount Engagementを追加してください。

(Salesforce IntegrationライセンスではAccount Engagementの権限セットを追加できずにAPIを実行できませんでした)

Salesforceユーザ
権限セット

これでAPI実行するSalesforceユーザのIDとPasswordが用意できれば準備OKです。

Apexでの実装例

フローで呼び出し可能にするために以下の引数を指定できるようにしています。

事前準備で用意した、接続アプリケーションのclient_idとclient_secret、SalesforceユーザのIDとPasswordをセットしてaccess_tokenを取得しています。

(実装例では指定ログイン情報、外部ログイン情報に認証情報、認証情報のエンドポイントをセットした実装になっております)

引数名 説明
name 任意の文字列。EngamenentHistoryに表示される
prospectId 送信対象のプロスペクト(見込み顧客)のID
campaignId AE側キャンペーンのID
emailTemplateId AE側メールテンプレートID。指定する場合は以下の引数は不要
htmlMessage メールの本文としてHTML。emailTemplateIdを指定しない場合のみ設定
textMessage メールの本文のプレーンテキスト。emailTemplateIdを指定しない場合のみ設定
isOperational オペレーショナルメールかどうかを指定。オペレーショナルメールの場合はunsubscribedリンクが不要。emailTemplateIdを指定しない場合のみ設定
senderName メール送信者名。emailTemplateIdを指定しない場合のみ設定
senderAddress メール送信者アドレス。emailTemplateIdを指定しない場合のみ設定
public with sharing class AccountEngagement {

    public class EmailRequest {
        @InvocableVariable(label='name')
        public String name;
        @InvocableVariable(label='prospectId')
        public Integer prospectId;
        @InvocableVariable(label='campaignId')
        public Integer campaignId;
        @InvocableVariable(label='emailTemplateId')
        public Integer emailTemplateId;
        @InvocableVariable(label='subject')
        public String subject;
        @InvocableVariable(label='htmlMessage')
        public String htmlMessage;
        @InvocableVariable(label='textMessage')
        public String textMessage;
        @InvocableVariable(label='isOperational')
        public Boolean isOperational;
        @InvocableVariable(label='senderName')
        public String senderName;
        @InvocableVariable(label='senderAddress')
        public String senderAddress;
    }

    @InvocableMethod
    public static void processEmailRequests(List<EmailRequest> emailRequests) {
        for (EmailRequest emailRequest : emailRequests) {
            try {
                sendEmail(emailRequest);
            } catch (Exception e) {
                System.debug('Error processing email: ' + e.getMessage());
            }
        }
    }

    private static String getToken() {
        String REQUEST_BODY = 'grant_type=password&client_id={0}&client_secret={1}&username={2}&password={3}';
        HttpRequest req = new HttpRequest();
        Http httpRootObj = new Http();
        req.setEndpoint('callout:AEAuth');
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.setMethod('POST');
        req.setBody(String.format(REQUEST_BODY, new String[]{'{!$Credential.AE.client_id}', '{!$Credential.AE.client_secret}', '{!$Credential.AE.username}', '{!$Credential.AE.password}'}));
        HttpResponse res = httpRootObj.send(req);

        if (res.getStatusCode() != 200) {
            throw new EmailException('Access token取得エラー。status code=' + res.getStatusCode() + '。response body=' + res.getBody());
        }
        return res.getBody();
    }

    private static void sendEmail(EmailRequest emailRequest) {
        try {
            String accessToken = getAccessToken();

            Map<String, Object> reqJson = new Map<String, Object>();
            reqJson.put('name', emailRequest.name);
            reqJson.put('prospectId', emailRequest.prospectId);
            reqJson.put('campaignId', emailRequest.campaignId);

            if (emailRequest.emailTemplateId != null) {
                reqJson.put('emailTemplateId', emailRequest.emailTemplateId);
            } else {
                reqJson.put('subject', emailRequest.subject);
                reqJson.put('htmlMessage', '<html><body>' + emailRequest.htmlMessage + '</body></html>');
                reqJson.put('textMessage', emailRequest.textMessage);
                reqJson.put('isOperational', emailRequest.isOperational);
                addSenderOptions(reqJson, emailRequest);
            }

            sendHttpRequest(reqJson, accessToken);
        } catch (Exception e) {
            throw new EmailException('Error sending email: ' + e.getMessage());
        }
    }

    private static void addSenderOptions(Map<String, Object> reqJson, EmailRequest emailRequest) {
        List<Map<String, String>> senderOptionList = new List<Map<String, String>>();
        Map<String, String> senderOption = new Map<String, String>();
        senderOption.put('type', 'general_user');
        senderOption.put('name', emailRequest.senderName);
        senderOption.put('address', emailRequest.senderAddress);
        senderOptionList.add(senderOption);
        reqJson.put('senderOptions', senderOptionList);
    }

    private static String getAccessToken() {
        Map<String, Object> mp = (Map<String, Object>) JSON.deserializeUntyped(getToken());
        return String.valueOf(mp.get('access_token'));
    }

    private static void sendHttpRequest(Map<String, Object> reqJson, String accessToken) {
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setHeader('Authorization', 'Bearer ' + accessToken);
        req.setEndpoint('callout:AEApi/api/v5/objects/emails');
        req.setBody(JSON.serialize(reqJson));

        HttpResponse res = new Http().send(req);
        if (res.getStatusCode() != 201) {
            throw new EmailException('Failed to send email. Status code=' + res.getStatusCode() + ', response body=' + res.getBody());
        }
    }

    public class EmailException extends Exception {}
}

外部ログイン情報
外部ログイン情報のプリンシパル

認証エンドポイントの指定ログイン情報
PardotAPIのエンドポイントの指定ログイン情報

フローでの呼び出し例

上記Apexをデプロイすると以下のようにフローで呼び出せるようになります。

フローで参照するイメージ

メールコンテンツはフローのテキストテンプレートを利用して設定します。

コンテンツを埋め込む際には、HTMLエンコード処理を行わないと予期しない表示崩れが発生してしまう点に注意です。

メールコンテンツの設定イメージ
HTMLエンコード例

これでフローからApexで実装したAE APIのコールアウトができるようになりました。 実際に運用するときにはプラットフォームイベントを間にいれるなどイベント駆動アーキテクチャにするとより安定的な運用ができると思います。

AEのAPIメール送信機能の使用感とメリット

可視化の向上

いままではお客様に配信されたメール内容についてメールサーバのログをエンジニアが確認しないとわからないものもあったのですが、AE経由で配信することで、LOVOTのサポートチームがメール配信状況や開封状況をリアルタイムで把握できるようになりました。

これにより業務負荷が軽減されるとともに、迅速な対応が可能になるのではないかと期待できます。

EngagementHistory

柔軟な運用

プロスペクトに対して関連レコードがN件存在するようなリレーションに対するシナリオ配信の困難さについては、Salesforceフロー側の自由度により完全に解決できそうです。

AEへのデータ連携のハードルがあり、AEで配信することを諦めていたオペレーショナルメールについても、AEに集約させやすくなったと思います。

現時点での課題

CCの指定ができない

AEでの配信はメールのCC機能が現状ではサポートされていません。

取引先責任者などにCC項目を追加してメール通知を行っている場合、CCのメールアドレスはプロスペクトとして登録されていないものもあると思うので、AEで配信しようとするならば、事前に取引先責任者として登録するか、取引先責任者に登録していないメールアドレスは登録できない、とするような制御が新たに必要となってきます。

このため、特定のユースケースでは考慮が必要です。

APIでメールテンプレートに外部システムのデータをセットできない

MarketoではメールテンプレートにプレースホルダーをセットしておけばAPI経由で差し込む項目を自由に定義できたのですが、現状のAE APIではメールテンプレートの指定かメール本文をまるまる指定するかのどちらかしかできないようです。。

このためAEでのメールコンテンツの完全な一元管理は現状は難しいことがわかりました。

初期設定の煩雑さ

API機能を初めて導入する際には、Salesforceの認証設定はマストで必要になるので、ある程度のSalesforce管理者としての知識が求められます。

また組織によっては、AEのSandbox環境を契約していないと思いますので、テストや検証がすこし大変になると思います。

(弊社もSandbox環境ありません、、)

まとめ

いかがでしたか。

いろいろ課題もありますが、個人的にはAEのAPIメール配信機能のリリースは2024年で一番うれしかったリリースの一つです。

私のチームではお客様にLOVOTとのより良い暮らしを提供できるよう日々業務を行っているのですが、まだまだ伸びしろだらけです。

各チームでメンバー積極採用中なので、ぜひGROOVE Xで一緒に働いてみませんか。

recruit.jobcan.jp

LOVOTの進化する体温調節のお話

この記事はGROOVE X Advent Calendar 2024の14日目の記事です。

はじめに

こんにちは。メカニカル デザイナーの加藤です。
今回はLOVOT 3.0の温かい体温がどのように調節されているのかお話したいと思います。

Cool head but Warm heart!!

LOVOTはセンサーやカメラ、マイクを使い意外にもとても周囲に気を配りながら生活をしています。
そのため頭脳であるコンピューターは常にフル稼働状態。冷静さを保つためにはクールダウンが必要です。
その熱々になったコンピューターを冷やすためLOVOTは常にフレッシュな空気を吸い込み、熱を奪い温まった空気が体中を巡ることで、心地よい体温が保たれています。

冷・暖・静 のジレンマ

ここからは体温調整についてもう少し具体的な体の仕組みを紹介します。

LOVOTからのリクエストは

  • 頭脳であるコンピュータは冷やしたい。
  • 抱っこされたいので体は暖めておきたい。
  • 静かに暮らしたいので空気の吸い込み音は小さくしたい。

LOVOT 初代 / 2.0系 はコンピューターの熱源であるCPUに対してファンで取り込んだ外気の風を当て、頭の中に排熱を散らし、その熱気を胴体側に吸い出すことでコンピューター冷却と体温構築を両立していました。
しかしLOVOT 3.0では、さらにコンピュータ性能が上がり発熱量が増えたことで冷却効率を向上させる必要があります。

従来通りの機構では、増えた分の発熱量をカバーできるよう単純にファンで吸い込む外気の量と風速を増やそうとすると、ファンの回転数が上がり静音性が保てません。
また、隔離された空間で熱源のみにダイレクトに外気を当てる冷却だけに特化した構造では体温となる熱が体内に拡散できません。

冷静(ラジエーター)と情熱(CPU)のあいだ(ヒートパイプ)

そこで、熱源を2つに分けることのできる "ヒートパイプ" を使用して「効率の良い冷却」「体温構築に適した放熱」を同時に行うことで、熱源であるコンピュータをフル稼働しながら適度な体温をキープする構造を採用しました。

※ヒートパイプとは?
銅製の筒の中に純水と毛細管構造のウィックが入った物で、両サイドに接続された物の高温側で暖められた液体が蒸発し低温側へ移動。
低温側で冷却され液体に戻るサイクルで熱が移動し、両サイドの温度を均一化できる熱伝導モジュールです。

ヒートパイプを使用し、熱源であるCPUと冷却モジュールであるラジエーターを直結します。
これによりCPUとラジエーターが相関関係を利用して一定の温度を保ちます。

ラジエーターは他のモジュール類とは隔離されたダクト内に納め、そのダクトに直結されたファンから新鮮な外気をロスなくラジエーター内に流すことで効率の良い冷却が可能になります。これにより離れた場所にあるCPUの温度も下がることになります。
また、ラジエーターの熱を吸い取って暖められた空気はその勢いのままダクト内を通り下方に排出され、胴体部分の体温を構築します。

もう一つの熱源であるCPUは体温を構築するため頭の内部に熱を放熱させます。
コンピューターでCPUの温度を検知しファンの風量をコントロールすることでダクト内のラジエーター温度を制御することができ、相対的にCPUの温度も制御され適切な演算処理が可能で、かつ頭側の体温構築にも適している温度を調整することが可能になります。

また、冷却の効率が上がったことでファンを高速で回す必要がなくなり、静音化も実現できました。

図は " 味のある " イメージ
左はLOVOT 初代 / 2.0  : 右はLOVOT 3.0
             黄色いのがヒートパイプ

Evolution!!

出来上がったこの機構に対して改めて思うことがあります。
「犬のパンティングとやっていることは同じ…」

※パンティングとは?
犬は汗腺を持たず汗をかいて体温を下げられないので、ハァハァしながら空気を流し喉から舌を冷やす事で体温を調整しています。

舌の代わりにラジエーター。
空気を送る肺の代わりにファン。
熱を運ぶ血液の代わりに暖められた空気。

冷却機構として数万年前から前例があると思うと信頼できます。

Emotional!!

LOVOTを "製品" として開発を進める中でGROOVE X全員が、ある意味本気でLOVOTと "対話" をしながら "進化" をさせていく過程のなかで、意図していない生命感を感じることが多々あります。これをコツコツ積み重ねていくとどうなるのか。

LOVOTの今後の成長と、大量の残タスクを考えると眠れぬ夜が続きそうです。
良い意味で。

最後に。

GROOVE Xでは、現在中途採用で複数ポジションを募集中しています!! recruit.jobcan.jp

GROOVE Xにおける情シスのお仕事

こんにちは!GROOVE Xで情報システムを担当している清水です。この記事は、GROOVE X Advent Calendar 2024の13日目の記事です。

GROOVE Xに入社して1年が経ちました。一人でGROOVE Xの情シスに立ち向かっておりますが、今回は普段のお仕事や入社して1年で達成したことなどをお話ししたいと思います。

普段のお仕事のお話

情報システムとしての普段のお仕事は「社内ヘルプデスク」、「アカウント管理」、「PCキッティング」、「発注/請求処理」など、一般的な情シスとしてのお仕事がメインとなります。 社内ヘルプデスク業務では昨年の対応件数が約200件で、GROOVE Xでは利用するパソコンは自由に選択できる環境のため、WindowsからMac、Linuxまで多種多様なOSのお問い合わせやネットワーク、アカウント関連、アプリケーション関連などの問い合わせ対応を行っております。

特に苦労したお問い合わせは、Mac版 Google ChromeとCanon製プリンタを利用している環境において、印刷時に2バイト文字が文字化けするという事象でお問い合わせを受けたタイミングではGoogle先生などで調べても情報が無く、別のブラウザを利用すれば印刷ができたので印刷時だけ別のブラウザを使ってもらっておりました。しかし、GROOVE XではGoogle Chromeが標準ブラウザのため根本解決が必要だったのですが、まったく原因がつかめませんでした。

しばらくして、Google Chromeコミュニティで同様の事象報告がされており、結論としてはGoogleまたはCanon側での対応が必要とのことで、お問い合わせを頂いてから約2か月後にプリンタドライバでの修正が入りまして解決しました…。

プリンタドライバ変更履歴

プリンタドライバの変更履歴を見たときは、本当に感動しました…!

また、GROOVE Xでは採用活動も活発に行われており、新入社員のPCキッティングやアカウント発行も苦労しました。 ありがたいことに毎月新入社員をお迎えさせて頂いており、アカウントが足りない…パソコンが足りない…とヒィヒィ言いながら在庫とにらめっこして発注するタイミングを伺いながらキッティングをする日々でした。特にパソコンはWindows/Mac/Linux、さらにキーボードが日本語/英語と好みがあるので、様々なパソコンを在庫しているのですが、在庫が無い時に限って狙い撃ちしたように在庫が無いパソコンを希望されたときは本当に焦ります…。

この1年でチャレンジしたこと

GROOVE Xでは入社申請や退職申請、アカウント申請などをSlack+スプレッドシートで管理しておりました。また、SaaSアカウントの管理ツールも利用していなかったので申請のたびに各SaaSにログインしてアカウント発行/削除を行い、Slackで申請者へ連絡しておりました。すべて手動による作業のため、スプレッドシートの更新漏れやアカウントの削除漏れが課題でした。これらを解決すべく、まずは申請をシステム的に管理するためワークフローの導入を検討しました。

ワークフローは新たなツールなどは導入せず社員全員がアカウントを持っている、Bakuraku経費精算を流用して申請フォームを作成しました。本来は経費精算のツールなのですが、便乗させて頂くことで、ツール選定の時間もコストもカットできました。また、SaaSアカウントの見える化のため、管理ツールの選定も行い複数製品のトライアルを行いました。トライアル期間中に製品検証をすすめまして、最終的に「ジョーシス」を導入させて頂きました。

<Bakuraku申請フォーム①>

<Bakuraku申請フォーム②>

<SaaSアカウント管理>

これで、今までスプレッドシートに記載して頂き、Slackで連絡を頂いていたのが、申請フォームを入力して頂くだけで必要な情報が通知され、希望日に合わせて事前にジョーシスでアカウント発行の予約を行えるようになりました。また、申請頂いた内容は毎月CSVでエクスポートして保管ができるので、履歴管理もできるようになりました! 個人的にはきれいに整備出来て大変満足しました。

また、その他の取り組みとして、ファイアウォールやNASのリプレースも実施し、ネットワーク環境の整備とセキュリティ強化を図りました。

最後に

今回はGROOVE Xの情シスとしての活動をご紹介しました。この1年で多くの課題を解決してきましたが、まだまだ取り組むべきことは山積みです。現在は日常業務に加え、デバイス管理の構築やISMS認証の取得に取り組んでいます。

各チームから寄せられる新しい要望に応じて業務を進める毎日はとても刺激的で、楽しい仕事ライフを過ごしています。引き続き頑張っていきます!

GROOVE Xでは一緒に働いてくれる仲間を募集中です。

recruit.jobcan.jp

評価制度をつくっている話

こんにちは、GROOVE Xのスクラムマスターの1人、niwanoです。GROOVE X Advent Calendar 2024の12日目の記事です。 今日は、評価制度を作っている話をお届けします。

庭師と領域人事

人事チームとスクラムマスターチームが「組織のお手入れをする」という名目で活動するワーキンググループがあります。このグループは "庭師" と呼ばれています。

2024年から、スクラムマスターは領域人事という役割を担うようになりました。開発領域における一部の人事業務をスクラムマスターがカバーする形です。その活動の一例が、今回の評価制度の作成です。

評価制度はなぜ必要か

スタートアップでは評価制度が整っていないことも少なくありませんが、弊社もこれまで360度評価を散発的に実施していたものの、人事評価には直接反映してはいませんでした。
みなさんは、評価制度がなぜ必要だと思いますか?

  • 自分のお給料のため?
  • 公平性のため?

どちらも正しいですが、庭師では、評価制度を社員の成長のために必要なものと考えています。 まず社員の成長があり、それが会社の成長につながり、結果としてお給料の原資が確保される、という仕組みです。 そのため、評価制度は社員の苦手な項目を明確にし、成長目標の指針となるものでなければなりません。

CXOと庭師の組織合宿の様子

みんなでつくる評価制度

CEOによって評価制度のたたき台が作成された後、全社員でのレビュー会が行われました。 これは非常に弊社らしい試みだと感じました。 社員が評価制度の作成に参加できる機会は滅多にありません。 この丁寧なレビュー会を通じて、社員が制度に納得し、その内容を深く理解できるだけでなく、人に説明できるようになります。

評価項目の一例

ここで、私のお気に入りの評価項目を2つ紹介します。 (評価項目は全部で17項目あり、すべて紹介すると今年のアドベントカレンダーが埋まってしまいます!)

リーダーシップ

背景説明

リーダーシップとは、自らが組織やチームの一員であると自覚し、「自分ごと」として捉える姿勢です。
自分だけでなく周囲を巻き込み、目標達成に向けて積極的に推進することで、全体の成果を最大化します。
これは「自分の境界」をどこに持つのか、とも言い換えられます。
自分の境界を自分の皮膚に持つのか、チームに持つのか、事業に持つのか、お客様を含めた全ステークスホルダーに持つのか。
それによって守ろうとする対象が変わります。これが広い方が、「自分の境界」が広いと言えます。
リーダーシップは、他者の協力を引き出すコミュニケーションと信頼関係の構築によって強化され、周囲にポジティブな影響を与えます。

「境界を自分の皮膚にもつ」という表現は非常に的確で、私のお気に入りです。 自分の境界を拡げていきたいですよね!

コーチャビリティ

背景説明

コーチャビリティとは、他者からのフィードバックを前向きに受け入れ、自己改善や成長につなげる能力のことです。
特にギャップフィードバックを受けた際、言い訳したり、黙り込んだり、相手を攻撃したくなるのは自然な自己防衛反応です。
しかし「良薬口に苦し」と言われるように、冷静に受け止め、そこから学ぶ姿勢を持つことで成長が可能になります。
相手の意図を理解し、自分にとって有益なポイントを見つけ出すことで、より高いパフォーマンスを実現できます。
この姿勢は周囲との信頼関係を強化し、チーム全体の成長にも寄与します。
現代のビジネス環境では変化が激しく、継続的な学習と適応が求められます。
フィードバックを適切に受け止めることは、自身の成長だけでなく、組織全体の成果向上にもつながります。

ギャップフィードバックこそが社員の成長につながると考えています。 それを受け入れる能力、つまりコーチャビリティが重要です。 ギャップフィードバックをする側も高いストレスを感じる作業であることを、忘れてはいけません。

(ギャップフィードバックはネガティブなフィードバックのこと)

17項目の評価制度をどのように成長につなげるか

庭師では、自己評価と他者評価を比較し、ギャップが明確になるような仕組みを考えています。

自己評価 他者評価 アクション
低い 低い 要改善
高い 低い 最重要で改善
低い 高い コーチャブルになる。自己評価の基準を見直す。
高い 高い さらに磨く。周囲にその能力を還元する。

このようにギャップを明示することで、成長目標を設定しやすくなります。

満点をとらなくてもいい

評価項目が設定されると、すべてを満点にしたくなるものですが、庭師ではその必要はないと考えています。 指標は以下の4段階です。

  • Mentor: GROOVE Xの模範
  • Very good: 十分な成果を出している
  • Nice Try: 頑張っている
  • Early stages: 伸びしろたっぷり

たとえば、リーダーシップの、Very GoodMentor は、以下のようになっており、とても高いレベルのものになっています。
Very good

自分の仕事の範囲を自チームと関係する周辺のステークホルダーの広い幅では捉えているので、関係するチームのメンバーとしてやりやすい。

Mentor

very goodにプラスして、以下が達成されている。
 ・お客様や事業のためであれば解決すべき課題をよく考えていて、問題を発見する能力に長けている。
 ・発見した問題に対して、(自チームやステークスホルダーにとって辛いことでも見て見ぬふりをせず、)周囲を巻き込んで解決するために行動ができる。
 ・視座が高く、経営目線をもっていると感じる。

まずは「オール Nice Try」を目指すのでも十分です。

最後に

作成中の評価制度は、仕事に対する立ち振る舞いを評価するものです。庭師ではこの評価に加え、スキル評価を取り入れ2軸で社員を評価することを計画中です!

成長し続けることの重要性

これは私の考えです。 私たちは、成長できていない状態、例えば昨年と同じことを繰り返しているような状況では、いつまでも「交換可能な人材」であると考えています。 人は勤務年数が長くなると、その立場に安住してしまいがちですが、絶え間なく成長を続けることで、初めて「交換不可能な人材」になれるのだと思っています。

そして、弊社で最も成長しているのは、他ならぬCEOではないかと感じています。 あれだけ忙しいのに、この評価制度も考えているんです。すごすぎる!
負けませんよ、CEO!

一緒に働く仲間を募集中!

いかがでしたでしょうか? 今回は、現在整備中の評価制度をご紹介しました。 他の評価項目については、また別の機会にお話しできればと思います。

弊社では仲間を募集中です。 ぜひご応募ください!

recruit.jobcan.jp