Robot School is the knowledge & learning centre for the Automation Cloud automation cloud

Let's make an app to solve the challenge from the previous lesson.

Under the hood, an Automation Job will load a web-page, go through its content picking up the bits as prescribed by the Script, and produce the data for the app to display.

The Script for the Job gets published to the Automation Cloud and executes remotely. The app receives notifications about Job state updates, requested inputs and emitted outputs.

Job Prerequisites

With your Automation Cloud account:

  1. Create an Application to obtain authentication credentials (secret key).
  2. Save your Script to a Service in the Automation Cloud.
  3. Connect the Service and the Application.

Scripting part

Let's keep it simple yet illustrative. Here is the idea:

  • Job navigates to this URL and emits the ingredients output for a user to review.
  • When a user provides an ingredientToAvoid input, Job can proceed with the data extraction.
  • Eventually, Job emits the menu output: a list of meals, excluding those with the ingredient to avoid, if any.

My result is in the sidebar on the right. Feel free to download and explore →

Coding part

JS Client library works in NodeJS 12+ and the latest browser environments.

Node example

Check the code below. Feel free to explore this interactive notebook , and observe how an Automation Job gets created, goes through a few state changes and finally outputs the data.

const { Client } = require('@automationcloud/client');

// Create Client instance
const client = new Client({
    serviceId: '691030cf-57ae-47bc-b863-75e9a12f973e',
    auth: process.env.SECRET_KEY // << Secret
});

// Create the Job. Let's start with no input whatsoever.
const job = await client.createJob();

// Subscribe to Job state updates to know what's happening.
job.onStateChanged(newState => console.log(`job: ${newState}`));

// Once the list of ingredients is ready...
job.onOutput('ingredients', async ingredients => {
    console.log('output: ingredients', ingredients);

    // Pick first and return to the Job as an input
    const ingredientToAvoid = ingredients[0];
    await job.submitInput('ingredientToAvoid', ingredientToAvoid);
    console.log('input: ' + ingredientToAvoid);
});

// Wait for the Job to finish. Resolves once the job reaches
// the "success" state (e.g. enters a "success" context).
await job.waitForCompletion();

// And finally, let's get the "menu" output
const output = await job.getOutput('menu');
console.log('output: menu', output);

Browser example

There is a limitation with browsers: it's not ok to use authentication credentials (secrets), exposing sensitive information to the outside world. As a solution, consider the following two-step approach:

STEP 1: On the server-side, start the Job and obtain your Job specific accessToken.

const { Client } = require('@automationcloud/client');

post('/', async (req, res) => {
    const serviceId = '691030cf-57ae-47bc-b863-75e9a12f973e';

    // Create Client instance
    const client = new Client({
        serviceId,
        auth: process.env.SECRET_KEY // << Secret
    });

    // Create Job
    const job = await client.createJob();

    // Get access token
    const accessToken = await job.getAccessToken();

    // Respond with secure credentials
    res.send({
        serviceId,
        jobId: job.jobId,
        accessToken
    });
});

Here is the interactive runkit notebook for you to explore.

STEP 2: In the browser, use serviceId and accessToken to create a Client instance, then pick up the Job by jobId and proceed with all the things. Check the code below.

import { Client } from '@automationcloud/client';

// Call the endpoint to obtain credentials
const res = await fetch(
    'https://school-menu-job-init-szydqtonfa6f.runkit.sh/',
    { method: 'POST' }
);
const { serviceId, jobId, accessToken } = await res.json();

// Create Client instance
const client = new Client({
    serviceId,
    auth: accessToken // << Your access token
});

// Pick up the Job
const job = await client.getJob(jobId);

// Proceed with the Job safely
job.onAwaitingInput('ingredientToAvoid', async () => await 'almond');
await job.waitForCompletion();

Here is a live example for you to play. It calls the endpoint based on the "Step 1: Start the Job" code to obtain credentials, then proceeds with all the other things front-end.