Skip to content

Agent Management Client for Java

Introduction

The Agent Management Java client allows you to onboard, offboard, update and delete agents. It provides connectivity functions to enable communication with the MindSphere Platform.

See Agent Management for more information about the service.

Hint

In the IoT context, assets are referred to as entity and aspects as propertyset. The following code samples switch between these terms depending on the used APIs.
Placeholders in the following samples are indicated by angular brackets < >.

Agent Operations

The Agents client lists, creates, updates, reads and deletes agents.

Client name: AgentsClient

Basic Agent Management

Create an Agent

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Construct the AgentsClient object
AgentsClient agents_client = AgentsClient.builder()
                                        .mindsphereCredentials(<credentials>)
                                        .restClientConfig(<config>)
                                        .build();

Agent agent = null;
try {
  agent = agents_client.createAgent(<agent_input>);
}catch (MindsphereException e) {
  // Exception handling
}

Create an Agent with SHARED_SECRET Security Profile

1
2
3
4
5
6
7
// Construct the AgentsClient object as shown above
Agent agent = null;
try {
  agent = agents_client.createAgentWithSharedSecret(<entity_id>, <agent_name>);
}catch (MindsphereException e) {
  // Exception handling
}

Create an Agent with RSA Security Profile

1
2
3
4
5
6
7
// Construct the AgentsClient object as shown above
Agent agent = null;
try {
  agent = agents_client.createAgentWithRSA(<entity_id>, <agent_name>);
}catch (MindsphereException e) {
  // Exception handling
}

List all Agents

Get all agents for the given filter input.

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.getAllAgents(<filter>, <size>, <page>, <sort>);
} catch (MindsphereException e) {
  // Exception handling
}

Get an Agent by ID

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
Agent agent = null;

try {
  agent = agents_client.getAgentByID(<agent_id>);
} catch (MindsphereException e) {
  // Exception handling
}

Update an Agent

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
Agent agent = null;

try {
  agent = agents_client.updateAgent(<agent_id>, <agent_update>, <ifMatch>);
} catch (MindsphereException e) {
  // Exception handling
}

Delete an Agent

1
2
3
4
5
6
// Construct the AgentsClient object as shown above
try {
  agents_client.deleteAgent(<agent_id>, <ifMatch>);
} catch (MindsphereException e) {
  // Exception handling
}

Get an Agent's Online Status

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
OnlineStatus online_status = null;

try {
  online_status = agents_client.getAgentOnlineStatus(<agent_id>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents using Filters

Get Agents with a Specific Name

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByName(<filter_name>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents with a Name from a List

Get a list of agents with either of the specified names.

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByNameIn(<filter_name_1>, <filter_name_2>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents with a Specific Name in Descending Order

Get a list of agents with a specific name sorted in descending order.

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByNameInDescendingOrder(<filter_name>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents where the Name Starts with a Specific String

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByNameStartsWith(<filter_string>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents where the Name Ends with a Specific String

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByNameEndsWith(<filter_string>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents where the Name Contains a Specific String

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByNameContains(<filter_string>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents with a Specific ID

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByAgentId(<filter_id>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents with an ID from a List

Get a list of agents with either of the specified IDs.

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByIdIn(<filter_id_1>,<filter_id_2>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents where the ID Starts with a Specific String

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByIdStartsWith(<filter_string>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents where the ID Ends with a Specific String

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByIdEndsWith(<filter_string>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents where the ID Contains a Specific String

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.filterAgentsByIdContains(<filter_string>);
} catch (MindsphereException e) {
  // Exception handling
}

Get Sorted Lists of Agents

Get Agents Sorted by Name

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.sortAgentsByName();
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents Sorted by Name in Descending Order

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.sortAgentsByNameDescendening();
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents Sorted by ID

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.sortAgentsById();
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents Sorted by ID in Descending Order

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.sortAgentsByIdDescendening();
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents Sorted by Entity ID

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.sortAgentsByEntityId();
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents Sorted by Entity ID in Descending Order

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.sortAgentsByEntityIdDescendening();
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents Sorted by Security Profile

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.sortAgentsBySecurityProfile();
} catch (MindsphereException e) {
  // Exception handling
}

Get Agents Sorted by Security Profile in Descending Order

1
2
3
4
5
6
7
8
// Construct the AgentsClient object as shown above
AgentsList agents_list = null;

try {
  agents_list = agents_client.sortAgentsBySecurityProfileDescendening();
} catch (MindsphereException e) {
  // Exception handling
}

Default Settings Operations

The Agents Default Setting client is used to get the access token, client assertion and keys for RSA profile.

Client name: AgentsDefaultSettingClient

Get an Access Token

Access tokens are used to access MindSphere services. They can be fetched in the following ways:

  1. Create an agent, onboard the agent and fetch an access token.

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    // Construct the AgentsDefaultSettingClient object
    AgentsDefaultSettingClient agents_default_setting_client = AgentsDefaultSettingClient.builder()
                                            .mindsphereCredentials(<credentials>)
                                            .restClientConfig(<config<)
                                            .build();
    
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessToken();
    }catch (MindsphereException e) {
      // Exception handling
    }
    
  2. Create an agent with the given asset ID, name and security profile. Onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessToken(<entity_id>, <agent_name>, <profile>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    
  3. Create an agent with the given asset ID and name, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessToken(<entity_id>, <agent_name>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    

Get an Access Token with SHARED_SECRET

Access token with SHARED_SECRET security profile can be fetched in the following ways:

  1. Create an agent with SHARED_SECRET security profile, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenWithSharedSecret();
    }catch (MindsphereException e) {
      // Exception handling
    }
    
  2. Create an agent with SHARED_SECRET security profile for the given tenant, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenWithSharedSecret(<tenant_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    

Get an Access Token with RSA

Access token with RSA security profile can be fetched in the following ways:

  1. Create an agent with RSA security profile, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenWithRSA();
    }catch (MindsphereException e) {
      // Exception handling
    }
    
  2. Create an agent with RSA security profile for the given tenant, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenWithRSA(<tenant_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    

Get an Access Token for an Asset

Access token for an asset can be fetched in the following ways:

  1. Create an agent for the given asset ID, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenForEntity(<entity_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    
  2. Create an agent for the given asset ID and tenant, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenForEntity(<entity_id>, <tenant_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    

Get an Access Token for an Asset Type

Access token for an asset type can be fetched in the following ways:

  1. Create an agent for the given asset type, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenForAssetType(<asset_type_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    
  2. Create an agent for the given asset type and parent ID, onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenForAssetType(<asset_type_id>, <asset_parent_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    
  3. Create an agent for the given asset type, parent ID and tenant. Onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenForAssetType(<tenant_id>, <asset_type_id>, <asset_parent_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    

Get an Access Token for an Agent

Access token for an existing agent can be fetched in the following ways:

  1. Onboard the agent and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenForAgent(<agent_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    
  2. Onboard the agent for a given tenant and fetch an access token.

    1
    2
    3
    4
    5
    6
    7
    // Construct the AgentsDefaultSettingClient object as shown above
    CreatedObjects created_objects = null;
    try {
      created_objects = agents_default_setting_client.getAccessTokenForAgent(<agent_id>, <tenant_id>);
    }catch (MindsphereException e) {
      // Exception handling
    }
    

Onboard with Onboarding Configuration and Get an Access Token

Onboard the agent with a given configuration and fetch an access token.

1
2
3
4
5
6
7
// Construct the AgentsDefaultSettingClient object as shown above
CreatedObjects created_objects = null;
try {
  created_objects = agents_default_setting_client.getAccessTokenWithOnBoardingConfig(<boarding_config>);
}catch (MindsphereException e) {
  // Exception handling
}

Note

The boardingConfig object can be retrieved via boardingClient.getBoardingConfiguration(agentId).

Get an Access Token when Status is ONBOARDING

Onboard the agent and fetch an access token when its status is ONBOARDING.

1
2
3
4
5
6
7
// Construct the AgentsDefaultSettingClient object as shown above
CreatedObjects created_objects = null;
try {
  created_objects = agents_default_setting_client.getAccessTokenDuringStatusOnBoarding(<agent_id>);
}catch (MindsphereException e) {
  // Exception handling
}

Get Access Token after Onboarding with SHARED_SECRET

Fetch an access token when status is ONBOARDED for agents with SHARED_SECRET security profile.

1
2
3
4
5
6
7
// Construct the AgentsDefaultSettingClient object as shown above
AccessToken access_token = null;
try {
  access_token = agents_default_setting_client.getAccessTokenAfterOnBoardedWithSharedSecret(<agent_id>, <tenant>, <client_secret>);
}catch (MindsphereException e) {
  // Exception handling
}

Note

The clientSecret string can be retrieved via registrationClient.onBoardAgent().

Get Access Token using Client Assertion

Fetch an access token using client assertion.

1
2
3
4
5
6
7
// Construct the AgentsDefaultSettingClient object as shown above
AccessToken access_token = null;
try {
  access_token = agents_default_setting_client.getAccessTokenFromClientAssertion(<client_assertion>);
}catch (MindsphereException e) {
  // Exception handling
}

Note

The clientAssertion string can be retrieved via agentsDefaultSettingClient.getClientAssertionForSharedSecret() or agentsDefaultSettingClient.getClientAssertionForRSA().

Get Keys for RSA

Generate public and private keys for an agent with RSA security profile.

1
2
3
4
5
6
7
// Construct the AgentsDefaultSettingClient object as shown above
JWKModel model = null;
try {
  model = agents_default_setting_client.getKeysForRSAProfile();
}catch (MindsphereException e) {
  // Exception handling
}

Get Client Assertion for SHARED_SECRET

Generate client assertion for an agent with SHARED_SECRET security profile.

1
2
3
4
5
6
7
// Construct the AgentsDefaultSettingClient object as shown above
String client_assertion = null;
try {
  client_assertion = agents_default_setting_client.getClientAssertionForSharedSecret(<agent_id>, <tenant>, <client_secret>);
}catch (MindsphereException e) {
  // Exception handling
}

Get Client Assertion for RSA

Generate client assertion for an agent with RSA security profile.

1
2
3
4
5
6
7
// Construct the AgentsDefaultSettingClient object as shown above
String client_assertion = null;
try {
  client_assertion = agents_default_setting_client.getClientAssertionForRSAProfile(<agent_id>, <tenant>);
}catch (MindsphereException e) {
  // Exception handling
}

Agent Data Source Configuration Operations

The Data Source Configuration client gets, creates and updates the data source configuration.

Client name: DataSourceConfigurationClient

Get the Data Source Configuration

Get the data source configuration for an agent with the given ID.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Construct the DataSourceConfigurationClient object
DataSourceConfigurationClient data_source_configuration_client = DataSourceConfigurationClient.builder()
                                      .mindsphereCredentials(<credentials>)
                                      .restClientConfig(<config>)
                                      .build();

DataSourceConfiguration data_source_configuration_client = null;
try {
  data_source_configuration = data_source_configuration_client.getDataSourceConfiguration(<agent_id>);
} catch (MindsphereException e) {
  // Exception handling
}

Create the Data Source Configuration

Create the data source configuration for an agent with the given ID.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// Construct the DataSourceConfigurationClient object as shown above
//Create a DataSource object
DataSource data_sources_item = new DataSource();
data_sources_item.setName(<name>);
data_sources_item.setDescription(<description>);
data_sources_item.setDataPoints(<data_points>) {
data_sources_item.customData(<custom_data>) {

//Create a DataSourceConfigurationInput object
DataSourceConfigurationInput configuration = new DataSourceConfigurationInput();
configuration.setConfigurationId(<configuration_id>);
configuration.addDataSourcesItem(data_sources_item);

DataSourceConfiguration data_source_configuration = null;

try {
  data_source_configuration = data_source_configuration_client.createDataSourceConfiguration(<agent_id>, configuration);
} catch (MindsphereException e) {
  // Exception handling
}

Update the Data Source Configuration

Update the data source configuration for an agent with the given ID.

1
2
3
4
5
6
7
8
// Construct the DataSourceConfigurationClient object as shown above
DataSourceConfiguration data_source_configuration = null;

try {
  data_source_configuration = data_source_configuration_client.updateDataSourceConfiguration(<agent_id>, <configuration>, <ifMatch>);
} catch (MindsphereException e) {
  // Exception handling
}

Agent Boarding Operations

The Boarding client is used to offboard an agent and to get the boarding configuration and the boarding status.

Client name: BoardingClient

Get the Boarding Configuration

Get the boarding configuration of an agent with the given ID.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Construct the BoardingClient object
BoardingClient boarding_client = BoardingClient.builder()
                                      .mindsphereCredentials(<credentials>)
                                      .restClientConfig(<config>)
                                      .build();

BoardingConfiguration boarding_configuration = null;
try {
  boarding_configuration = boarding_client.getBoardingConfiguration(<agent_id>);
} catch (MindsphereException e) {
  // Exception handling
}

Offboard an Agent

Offboard an agent with the given ID.

1
2
3
4
5
6
7
8
// Construct the BoardingClient object as shown above
OnboardingStatus onboarding_status = null;

try {
  onboarding_status = boarding_client.offBoard(<agent_id>);
} catch (MindsphereException e) {
  // Exception handling
}

Get the Boarding Status

Get the boarding status of an agent with the given ID.

1
2
3
4
5
6
7
8
// Construct the BoardingClient object as shown above
OnboardingStatus onboarding_status = null;

try {
  onboarding_status = boarding_client.getBoardingStatus(<agent_id>);
} catch (MindsphereException e) {
  // Exception handling
}

Agent Registration Operations

The Registration client can register an agent and update agent information.

Client name: RegistrationClient

Register an Agent

Register an agent.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// Construct the RegistrationClient object
RegistrationClient registration_client = RegistrationClient.builder()
                                      .mindsphereCredentials(<credentials>)
                                      .restClientConfig(<config>)
                                      .build();

ClientIdentifier client_identifier = null;
try {
  client_identifier = registration_client.onBoardAgent(<initial_access_token>, <keys>);
} catch (MindsphereException e) {
  /

Note

The initialAccessToken string can be obtained via boardingClient.getBoardingConfiguration(agentId).

Register an Agent with SHARED_SECRET Security Profile

1
2
3
4
5
6
// Construct the RegistrationClient object
ClientIdentifier client_identifier = null;
try {
  client_identifier = registration_client.onBoardAgentWithSharedSecretProfile(<initial_access_token>);
} catch (MindsphereException e) {
  /

Register an Agent with RSA Security Profile

1
2
3
4
5
6
7
// Construct the RegistrationClient object
ClientIdentifier client_identifier = null;
try {
  client_identifier = registration_client.onBoardAgentWithRSAProfile(<initial_access_token>, <keys>);
} catch (MindsphereException e) {
  // Exception handling
}

Update Client Information for SHARED_SECRET Security Profile

Update client information of a client with the given ID.

1
2
3
4
5
6
7
8
// Construct the RegistrationClient object
ClientIdentifier client_identifier = null;

try {
  client_identifier = registration_client.rotateKeysForSharedSecret(<registration_access_token>, <client_id>);
} catch (MindsphereException e) {
  // Exception handling
}

Update Client Information for RSA Security Profile

Update client information of a client with the given ID.

1
2
3
4
5
6
7
// Construct the RegistrationClient object
ClientIdentifier client_identifier = null;
try {
  client_identifier = registration_client.rotateKeysForRSA(<registration_access_token>, <client_id>, <keys>);
} catch (MindsphereException e) {
  // Exception handling
}

Agent Token Operations

The Token client is used to get the access token and the key information of OAuth server.

Client name: AccessTokenClient

Fetch an Access Token

Fetch an access token.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
// Construct the AccessTokenClient object
AccessTokenClient access_token_client = AccessTokenClient.builder()
                                      .mindsphereCredentials(<credentials>)
                                      .restClientConfig(<config>)
                                      .build();

AccessToken access_token = null;
try {
  access_token = access_token_client.getAccessToken(<grant_type>, <client_assertion_type>, <client_assertion>);
} catch (MindsphereException e) {
  // Exception handling
}

Provide Key Information of OAuth Server

Provide key information of OAuth server.

1
2
3
4
5
6
7
// Construct the AccessTokenClient object as shown above
TokenKey token_key = null;
try {
  token_key = access_token_client.getPublicKeyFromServer(<ifNoneMatch>);
} catch (MindsphereException e) {
  // Exception handling
}

Any questions left?

Ask the community


Except where otherwise noted, content on this site is licensed under the MindSphere Development License Agreement.